diff --git a/Makefile b/Makefile index 63a1672891..37f00ccf2a 100644 --- a/Makefile +++ b/Makefile @@ -80,6 +80,7 @@ CWFLAGS=-Wall G_OFILES=\ g/a.o \ + g/e.o \ g/h.o \ g/i.o \ g/j.o \ diff --git a/g/e.c b/g/e.c index 9d9941e5f0..55778c12ba 100644 --- a/g/e.c +++ b/g/e.c @@ -11,13 +11,13 @@ /* u3_ce_fault(): handle a memory event with libsigsegv protocol. */ -static c3_i +c3_i u3_ce_fault(void* adr_v, c3_i ser_i) { if ( ser_i ) { c3_w* adr_w = (c3_w*) adr_v; - if ( (adr_w < u3_Loom) || (adr_w > (u3_Loom + u3_cc_size)) ) { + if ( (adr_w < u3_Loom) || (adr_w > (u3_Loom + u3_cc_pages)) ) { fprintf(stderr, "address %p out of loom!\r\n", adr_v); return 0; } @@ -42,36 +42,12 @@ u3_ce_fault(void* adr_v, c3_i ser_i) return 1; } -/* u3_ce_sync(): write a checkpoint at the current state. -*/ - - for ( ceg_u = &LoomSegmentA; ceg_u; ceg_u = ceg_u->nex_u ) { - if ( (pag_w >= ceg_u->bot_w) && - (win_w=(pag_w - ceg_u->bot_w)) < ceg_u->len_w ) - { - if ( win_w >= ceg_u->pgs_w ) { - ceg_u->pgs_w = win_w + 1; - } - break; - } - } - if ( 0 == ceg_u ) { - fprintf(stderr, "page %d is not in a segment!\n", pag_w); - return 1; - } - - return 1; - } - return 0; -} - /* _ce_image_open(): open or create image. yes if it already exists. */ static c3_o _ce_image_open(u3_cs_image* img_u) { c3_c ful_c[8193]; - c3_i fid_i; snprintf(ful_c, 8192, "%s", u3P.cpu_c); mkdir(ful_c, 0700); @@ -86,13 +62,13 @@ _ce_image_open(u3_cs_image* img_u) if ( -1 != (img_u->fid_i = open(ful_c, O_RDWR)) ) { struct stat buf_u; - if ( -1 == fstat(fid_i, &buf_u) ) + if ( -1 == fstat(img_u->fid_i, &buf_u) ) { perror(ful_c); c3_assert(0); return u3_no; } else { - c3_d siz_d = buf_u.st_siz; + c3_d siz_d = buf_u.st_size; c3_d pgs_d = (siz_d + (c3_d)((1 << (u3_cc_page + 2)) - 1)) >> (c3_d)(u3_cc_page + 2); @@ -119,71 +95,6 @@ _ce_image_open(u3_cs_image* img_u) } } -/* u3_ce_boot(): start the memory system. -*/ -void -u3_ce_boot(c3_c* cpu_c) -{ - /* Map at fixed address. - */ - { - void* map_v; - - map_v = mmap((void *)u3_Loom, - (u3_cc_size << 2), - PROT_READ, - (MAP_ANON | MAP_FIXED | MAP_PRIVATE), - -1, 0); - - if ( -1 == (c3_ps)map_v ) { - map_v = mmap((void *)0, - (u3_cc_size << 2), - PROT_READ, - MAP_ANON | MAP_PRIVATE, - -1, 0); - - if ( -1 == (c3_ps)map_v ) { - fprintf(stderr, "map failed twice\n"); - } else { - fprintf(stderr, "map failed - try U2_OS_LoomBase %p\n", map_v); - } - exit(1); - } - printf("loom: mapped %dMB\n", (u3_cc_size >> 18)); - } - - /* Open and load, or create, image files. - */ - { - u3P.cpu_c = cpu_c; - u3P.nor_u.nam_c = "north"; - u3P.sou_u.nam_c = "south"; - - if ( u3_yes == _ce_image_open(&u3P.nor_u) ) { - _ce_image_blit_north(&u3P.nor_u); - } - if ( u3_yes == _ce_image_open(&u3P.sou_u) ) { - _ce_image_blit_south(&u3P.sou_u); - } - } - - /* Open and apply any patches. - */ - { - u3_cs_patch* pat_u; - - if ( 0 != (pat_u = _ce_patch_read()) ) { - _ce_patch_memory(pat_u); - _ce_image_patch(pat_u, &u3P.nor_u, &u3P.sou_u); - - _ce_image_fsync(&u3P.nor_u); - _ce_image_fsync(&u3P.sou_u); - - _ce_patch_delete(); - } - } -} - /* _ce_patch_write_control(): write control block file. */ static void @@ -199,10 +110,9 @@ _ce_patch_write_control(u3_cs_patch* pat_u) /* _ce_patch_read_control(): read control block file. */ -static void +static c3_o _ce_patch_read_control(u3_cs_patch* pat_u) { - u3_cs_control* con_u; c3_w len_w; c3_assert(0 == pat_u->con_u); @@ -223,17 +133,17 @@ _ce_patch_read_control(u3_cs_patch* pat_u) { free(pat_u->con_u); pat_u->con_u = 0; - return u3_no; } + return u3_yes; } /* _ce_patch_create(): create patch files. */ -static c3_i +static void _ce_patch_create(u3_cs_patch* pat_u) { - c3_i fid_i; + c3_c ful_c[8193]; snprintf(ful_c, 8192, "%s", u3P.cpu_c); mkdir(ful_c, 0700); @@ -242,24 +152,79 @@ _ce_patch_create(u3_cs_patch* pat_u) mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/control.bin", u3P.cpu_c); - if ( -1 == (pat_u->ctl_i = open(ful_c, O_WRONLY | O_CREAT | O_EXCL, 0666)) ) { + if ( -1 == (pat_u->ctl_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) { c3_assert(0); - return 0; } snprintf(ful_c, 8192, "%s/.urb/memory.bin", u3P.cpu_c); - if ( -1 == (pat_u->mem_i = open(ful_c, O_WRONLY | O_CREAT | O_EXCL, 0666)) ) { + if ( -1 == (pat_u->mem_i = open(ful_c, O_RDWR | O_CREAT | O_EXCL, 0666)) ) { c3_assert(0); - return 0; } } +/* _ce_patch_delete(): delete a patch. +*/ +static void +_ce_patch_delete(void) +{ + c3_c ful_c[8193]; + + snprintf(ful_c, 8192, "%s/.urb/control.bin", u3P.cpu_c); + unlink(ful_c); + + snprintf(ful_c, 8192, "%s/.urb/memory.bin", u3P.cpu_c); + unlink(ful_c); +} + +/* _ce_patch_verify(): check patch data mug. +*/ +static c3_o +_ce_patch_verify(u3_cs_patch* pat_u) +{ + c3_w i_w; + + for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) { + c3_w mug_w = pat_u->con_u->mem_u[i_w].mug_w; + c3_w mem_w[u3_cc_page]; + + if ( -1 == lseek(pat_u->mem_i, (i_w << (u3_cc_page + 2)), SEEK_SET) ) { + c3_assert(0); + return u3_no; + } + if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3_cc_page + 2))) ) { + c3_assert(0); + return u3_no; + } + { + c3_w nug_w = u3_cr_mug_words(mem_w, u3_cc_page); + + if ( mug_w != nug_w ) { + printf("_ce_patch_verify: mug mismatch (%x, %x)\r\n", mug_w, nug_w); + return u3_no; + } + } + } + return u3_yes; +} + +/* _ce_patch_free(): free a patch. +*/ +static void +_ce_patch_free(u3_cs_patch* pat_u) +{ + free(pat_u->con_u); + close(pat_u->ctl_i); + close(pat_u->mem_i); + free(pat_u); +} + /* _ce_patch_open(): open patch, if any. */ static u3_cs_patch* _ce_patch_open(void) { u3_cs_patch* pat_u; + c3_c ful_c[8193]; c3_i ctl_i, mem_i; snprintf(ful_c, 8192, "%s", u3P.cpu_c); @@ -269,13 +234,15 @@ _ce_patch_open(void) mkdir(ful_c, 0700); snprintf(ful_c, 8192, "%s/.urb/control.bin", u3P.cpu_c); - if ( -1 == (ctl_i = open(ful_c, O_RDONLY)) ) { + if ( -1 == (ctl_i = open(ful_c, O_RDWR)) ) { return 0; } snprintf(ful_c, 8192, "%s/.urb/memory.bin", u3P.cpu_c); - if ( -1 == (mem_i = open(ful_c, O_RDONLY)) ) { + if ( -1 == (mem_i = open(ful_c, O_RDWR)) ) { close(ctl_i); + + _ce_patch_delete(); return 0; } pat_u = malloc(sizeof(u3_cs_patch)); @@ -287,12 +254,96 @@ _ce_patch_open(void) close(pat_u->ctl_i); close(pat_u->mem_i); free(pat_u); + + _ce_patch_delete(); + return 0; + } + if ( u3_no == _ce_patch_verify(pat_u) ) { + _ce_patch_free(pat_u); + _ce_patch_delete(); return 0; } return pat_u; } -/* _ce_patch_compose(): make current patch. +/* _ce_patch_write_page(): write a page of patch memory. +*/ +static void +_ce_patch_write_page(u3_cs_patch* pat_u, + c3_w pgc_w, + c3_w* mem_w) +{ + if ( -1 == lseek(pat_u->mem_i, (pgc_w << (u3_cc_page + 2)), SEEK_SET) ) { + c3_assert(0); + } + if ( (1 << (u3_cc_page + 2)) != + write(pat_u->mem_i, mem_w, (1 << (u3_cc_page + 2))) ) + { + c3_assert(0); + } +} + +/* _ce_patch_count_page(): count a page, producing new counter. +*/ +static c3_w +_ce_patch_count_page(c3_w pag_w, + c3_w pgc_w) +{ + c3_w blk_w = (pag_w >> 5); + c3_w bit_w = (pag_w & 31); + + if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { + pgc_w += 1; + } + return pgc_w; +} + +/* _ce_patch_save_page(): save a page, producing new page counter. +*/ +static c3_w +_ce_patch_save_page(u3_cs_patch* pat_u, + c3_w pag_w, + c3_w pgc_w) +{ + c3_w blk_w = (pag_w >> 5); + c3_w bit_w = (pag_w & 31); + + if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { + c3_w* mem_w = u3_Loom + (pag_w << u3_cc_page); + + pat_u->con_u->mem_u[pgc_w].pag_w = pag_w; + pat_u->con_u->mem_u[pgc_w].mug_w = u3_cr_mug_words(mem_w, u3_cc_page); + + _ce_patch_write_page(pat_u, pgc_w, mem_w); + + if ( -1 == mprotect(u3_Loom + (pag_w << u3_cc_page), + (1 << (u3_cc_page + 2)), + PROT_READ) ) + { + c3_assert(0); + } + + u3P.dit_w[blk_w] &= ~(1 << bit_w); + pgc_w += 1; + } + return pgc_w; +} + +/* _ce_patch_junk_page(): mark a page as junk. +*/ +static void +_ce_patch_junk_page(u3_cs_patch* pat_u, + c3_w pag_w) +{ + if ( -1 == mprotect(u3_Loom + (pag_w << u3_cc_page), + (1 << (u3_cc_page + 2)), + PROT_READ) ) + { + c3_assert(0); + } +} + +/* _ce_patch_compose(): make and write current patch. */ static u3_cs_patch* _ce_patch_compose(void) @@ -312,34 +363,16 @@ _ce_patch_compose(void) sou_w = (swu_w + ((1 << u3_cc_page) - 1)) >> u3_cc_page; } - /* Count dirty pages in northward (low) section. + /* Count dirty pages. */ { c3_w i_w; - for ( i_w = 0; i_w < nor_w; i++ ) { - c3_w blk_w = (i_w >> 5); - c3_w bit_w = (i_w & 31); - - if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { - pgs_w += 1; - } + for ( i_w = 0; i_w < nor_w; i_w++ ) { + pgs_w = _ce_patch_count_page(i_w, pgs_w); } - } - - /* Count dirty pages in southward (high) section. - */ - { - c3_w i_w; - - for ( i_w = 0; i_w < sou_w; i++ ) { - c3_w j_w = (u3_cc_pages - (i_w + 1)); - c3_w blk_w = (j_w >> 5); - c3_w bit_w = (j_w & 31); - - if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { - pgs_w += 1; - } + for ( i_w = 0; i_w < sou_w; i_w++ ) { + pgs_w = _ce_patch_count_page((u3_cc_pages - (i_w + 1)), pgs_w); } } @@ -347,39 +380,115 @@ _ce_patch_compose(void) return 0; } else { - u3_cs_patch* pat_u = malloc(sizeof u3_cs_patch); + u3_cs_patch* pat_u = malloc(sizeof(u3_cs_patch)); c3_w i_w, pgc_w; _ce_patch_create(pat_u); - - /* Build and fill control block. - */ - { - pat_u->con_u = malloc(sizeof(u3_cs_control) + - (pgs_w + sizeof(u3_cs_line))); + pat_u->con_u = malloc(sizeof(u3_cs_control) + (pgs_w + sizeof(u3_cs_line))); + pgc_w = 0; - pgc_w = 0; - for ( i_w = 0; i_w < nor_w; i_w++ ) { - c3_w blk_w = (i_w >> 5); - c3_w bit_w = (i_w & 31); + for ( i_w = 0; i_w < nor_w; i_w++ ) { + pgc_w = _ce_patch_save_page(pat_u, i_w, pgc_w); + } + for ( i_w = 0; i_w < sou_w; i_w++ ) { + pgc_w = _ce_patch_save_page(pat_u, (u3_cc_pages - (i_w + 1)), pgs_w); + } + for ( i_w = nor_w; i_w < (u3_cc_pages - sou_w); i_w++ ) { + _ce_patch_junk_page(pat_u, i_w); + } + + _ce_patch_write_control(pat_u); + return pat_u; + } +} - if ( u3P.dit_w[blk_w] & (1 << bit_w) ) { - pgs_w += 1; - } +/* _ce_sync(): sync a file descriptor. +*/ +static void +_ce_sync(c3_i fid_i) +{ +#if defined(U2_OS_linux) + fdatasync(fid_i); +#elif defined(U2_OS_osx) + fcntl(fid_i, F_FULLFSYNC); +#elif defined(U2_OS_bsd) + fsync(fid_i); +#else +# error "port: datasync" +#endif +} + +/* _ce_patch_sync(): make sure patch is synced to disk. +*/ +static void +_ce_patch_sync(u3_cs_patch* pat_u) +{ + _ce_sync(pat_u->ctl_i); + _ce_sync(pat_u->mem_i); +} + +/* _ce_image_sync(): make sure image is synced to disk. +*/ +static void +_ce_image_sync(u3_cs_image* img_u) +{ + _ce_sync(img_u->fid_i); +} + +/* _ce_patch_apply(): apply patch to image. +*/ +static void +_ce_patch_apply(u3_cs_patch* pat_u) +{ + c3_w i_w; + + u3P.nor_u.pgs_w = pat_u->con_u->nor_w; + ftruncate(u3P.nor_u.fid_i, u3P.nor_u.pgs_w << (u3_cc_page + 2)); + + u3P.sou_u.pgs_w = pat_u->con_u->sou_w; + ftruncate(u3P.sou_u.fid_i, u3P.sou_u.pgs_w << (u3_cc_page + 2)); + + for ( i_w = 0; i_w < pat_u->con_u->pgs_w; i_w++ ) { + c3_w pag_w = pat_u->con_u->mem_u[i_w].pag_w; + c3_w mem_w[u3_cc_page]; + c3_i fid_i; + c3_w off_w; + + if ( pag_w < pat_u->con_u->nor_w ) { + fid_i = u3P.nor_u.fid_i; + off_w = pag_w; + } + else { + fid_i = u3P.sou_u.fid_i; + off_w = (u3_cc_pages - (pag_w + 1)); + } + + if ( -1 == read(pat_u->mem_i, mem_w, (1 << (u3_cc_page + 2))) ) { + c3_assert(0); + } + else { + if ( -1 == write(fid_i, mem_w, (1 << (u3_cc_page + 2))) ) { + c3_assert(0); } + } + } +} - c3_assert(0 == (u3P.dit_w[blk_w] & bit_w)); - u3P.dit_w[blk_w] |= (1 << bit_w); - - - /* Handle intermediate section. - */ - - /* - - pgs_w = 0; - for ( i_w = 0; i_w < (u3_cc_pages >> 5); i_w++ ) { +/* _ce_image_blit(): apply image to memory. +*/ +static void +_ce_image_blit(u3_cs_image* img_u, + c3_w* ptr_w, + c3_ws stp_ws) +{ + c3_w i_w; + lseek(img_u->fid_i, 0, SEEK_SET); + for ( i_w=0; i_w < img_u->pgs_w; i_w++ ) { + if ( -1 == read(img_u->fid_i, ptr_w, (1 << (u3_cc_page + 2))) ) { + c3_assert(0); + } + ptr_w += stp_ws; } } @@ -388,7 +497,109 @@ _ce_patch_compose(void) void u3_ce_save(void) { - u3_cs_patch* pat_u = _ce_patch_compose(); + u3_cs_patch* pat_u; - _ce_patch_save(pat_u); + // Write all dirty pages to disk; clear protection and dirty bits. + // + // This has to block the main thread. All further processing can happen + // in a separate thread, though we can't save again till this completes. + // + printf("_ce_patch_compose\r\n"); + pat_u = _ce_patch_compose(); + + // Sync the patch files. + // + printf("_ce_patch_sync\r\n"); + _ce_patch_sync(pat_u); + + // Copy the patch files into the image file. + // + printf("_ce_patch_apply\r\n"); + _ce_patch_apply(pat_u); + + // Sync the image file. + // + printf("_ce_image_sync\r\n"); + _ce_image_sync(&u3P.nor_u); + _ce_image_sync(&u3P.sou_u); + + // Delete the patchfile and free it. + // + printf("_ce_patch_delete\r\n"); + _ce_patch_delete(); + printf("_ce_patch_free\r\n"); + _ce_patch_free(pat_u); +} + +/* u3_ce_boot(): start the memory system. +*/ +void +u3_ce_boot(c3_c* cpu_c) +{ + /* Map at fixed address. + */ + { + c3_w len_w = (1 << (u3_cc_bits + 2)); + void* map_v; + + map_v = mmap((void *)u3_Loom, + len_w, + // PROT_READ, + PROT_READ | PROT_WRITE, + (MAP_ANON | MAP_FIXED | MAP_PRIVATE), + -1, 0); + + if ( -1 == (c3_ps)map_v ) { + map_v = mmap((void *)0, + len_w, + PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, + -1, 0); + + if ( -1 == (c3_ps)map_v ) { + fprintf(stderr, "map failed twice\n"); + } else { + fprintf(stderr, "map failed - try U2_OS_LoomBase %p\n", map_v); + } + exit(1); + } + printf("loom: mapped %dMB\n", len_w >> 20); + } + + /* Open and apply any patches. + */ + { + u3_cs_patch* pat_u; + + if ( 0 != (pat_u = _ce_patch_open()) ) { + printf("_ce_patch_apply\r\n"); + _ce_patch_apply(pat_u); + + printf("_ce_image_sync\r\n"); + _ce_image_sync(&u3P.nor_u); + _ce_image_sync(&u3P.sou_u); + + printf("_ce_patch_delete\r\n"); + _ce_patch_delete(); + printf("_ce_patch_free\r\n"); + _ce_patch_free(pat_u); + } + } + + /* Open and load, or create, image files. + */ + { + u3P.cpu_c = cpu_c; + u3P.nor_u.nam_c = "north"; + u3P.sou_u.nam_c = "south"; + + if ( u3_yes == _ce_image_open(&u3P.nor_u) ) { + _ce_image_blit(&u3P.nor_u, u3_Loom, (1 << u3_cc_page)); + } + if ( u3_yes == _ce_image_open(&u3P.sou_u) ) { + _ce_image_blit(&u3P.sou_u, + (u3_Loom + (1 << u3_cc_bits) - (1 << u3_cc_page)), + -(1 << u3_cc_page)); + } + } } diff --git a/g/m.c b/g/m.c index fedfadd61f..6a47552b31 100644 --- a/g/m.c +++ b/g/m.c @@ -46,13 +46,7 @@ u3_cm_file(c3_c* pas_c) static u3_road* _find_north(c3_w* mem_w, c3_w siz_w, c3_w len_w) { - c3_w* rut_w = mem_w; - c3_w* hat_w = rut_w; - c3_w* mat_w = ((mem_w + len_w) - siz_w); - c3_w* cap_w = mat_w; - u3_road* rod_u = (void*) mat_w; - - return rod_u; + return (void *) ((mem_w + len_w) - siz_w); } #if 0 @@ -127,11 +121,9 @@ _boot_parts(void) void u3_cm_boot(void) { - if ( u3_so(new_o) ) { - u3H = (u3_cs_home *)_boot_north(u3_Loom, c3_wiseof(u3_cs_home), len_w); - } - else { + c3_w len_w = (1 << u3_cc_bits); + u3H = (u3_cs_home *)_boot_north(u3_Loom, c3_wiseof(u3_cs_home), len_w); u3R = &u3H->rod_u; _boot_parts(); @@ -142,21 +134,12 @@ u3_cm_boot(void) void u3_cm_load(void) { + c3_w len_w = (1 << u3_cc_bits); + u3H = (u3_cs_home *)_find_north(u3_Loom, c3_wiseof(u3_cs_home), len_w); u3R = &u3H->rod_u; } -/* u3_cm_boot(): make u3R and u3H from nothing. -*/ -void -u3_cm_boot(void) -{ - u3H = (u3_cs_home *)_boot_north(u3_Loom, c3_wiseof(u3_cs_home), len_w); - u3R = &u3H->rod_u; - - _boot_parts(); -} - /* u3_cm_clear(): clear all allocated data in road. */ void diff --git a/g/v.c b/g/v.c new file mode 100644 index 0000000000..49e43592ef --- /dev/null +++ b/g/v.c @@ -0,0 +1,479 @@ +/* g/v.c +** +** This file is in the public domain. +*/ +#include +#include "all.h" + +/* _cv_nock_wish(): call wish through hardcoded interface. +*/ +static u3_noun +_cv_nock_wish(u3_noun txt) +{ + u3_noun fun = u3_cn_nock_on(u3k(u3A->roc), u3k(u3_cx_at(20, u3A->roc))); + + return u3_cn_slam_on(fun, txt); +} + +/* u3_cv_make(): make a new pier and instantiate pill. +*/ +void +u3_cv_make(c3_c* pas_c, u3_noun now) +{ + u3_noun sys = u3_cke_cue(u3_cm_file(pas_c)); + + printf("cv_make: loaded pill %s, as %x\n", pas_c, u3_cr_mug(sys)); + + u3A->ken = u3k(u3h(sys)); + + printf("cv_make: kernel %x, mug %x\n", u3A->ken, u3_cr_mug(u3A->ken)); + { + u3_noun cor = u3_cn_nock_on(0, u3k(u3A->ken)); + + printf("cv_make: activated kernel\n"); + u3z(cor); + } + u3A->roc = u3k(u3t(sys)); + u3z(sys); + + printf("cv_make: core mug %x\n", u3_cr_mug(u3A->roc)); + + u3_cv_time(now); + u3_cv_numb(); + + { + c3_c* wen_c = u3_cr_string(u3A->wen); + + printf("cv_make: time: %s\n", wen_c); + free(wen_c); + } +} + +/* u3_cv_gate(): load a kernel function. +*/ +u3_noun +u3_cv_gate(const c3_c* txt_c) +{ + u3_noun txt = u3_ci_string(txt_c); + u3_weak gat = u3_ckdb_get(u3k(u3A->yot), u3k(txt)); + + if ( u3_none == gat ) { + gat = _cv_nock_wish(u3k(txt)); + u3A->yot = u3_ckdb_put(u3A->yot, u3k(txt), u3k(gat)); + } + u3z(txt); + return gat; +} + +/* _cv_mung(): formula wrapper with gate and sample. +*/ + static u3_noun + _cv_mung_in(u3_noun gam) + { + u3_noun pro = u3_cn_slam_on(u3k(u3h(gam)), u3k(u3t(gam))); + + u3z(gam); return pro; + } +static u3_noun +_cv_mung(c3_w sec_w, u3_noun gat, u3_noun sam) +{ + u3_noun gam = u3nc(gat, sam); + + return u3_cm_soft(0, _cv_mung_in, gam); +} + +/* u3_cv_pike(): poke with floating core. +*/ +u3_noun +u3_cv_pike(u3_noun ovo, u3_noun cor) +{ + u3_noun fun = u3_cn_nock_on(cor, u3k(u3_cx_at(42, cor))); + u3_noun sam = u3nc(u3k(u3A->now), ovo); + + return _cv_mung(0, fun, sam); +} + +/* u3_cv_nick(): transform enveloped packets, [vir cor]. +*/ +u3_noun +u3_cv_nick(u3_noun vir, u3_noun cor) +{ + if ( u3_nul == vir ) { + return u3nt(u3_blip, vir, cor); + } + else { + u3_noun i_vir = u3h(vir); + u3_noun pi_vir, qi_vir; + u3_noun vix; + + if ( (u3_yes == u3_cr_cell((i_vir=u3h(vir)), &pi_vir, &qi_vir)) && + (u3_yes == u3du(qi_vir)) && + (c3__hear == u3h(qi_vir)) ) + { + u3_noun gon; + + gon = u3_cv_pike(u3k(i_vir), cor); + if ( u3_blip != u3h(gon) ) { + u3z(vir); + return gon; + } + else { + u3_noun viz; + + vix = u3k(u3h(u3t(gon))); + cor = u3k(u3t(u3t(gon))); + u3z(gon); + + viz = u3_ckb_weld(vix, u3k(u3t(vir))); + u3z(vir); + + return u3_cv_nick(viz, cor); + } + } + else { + u3_noun nez = u3_cv_nick(u3k(u3t(vir)), cor); + + if ( u3_blip != u3h(nez) ) { + u3z(vir); + return nez; + } else { + u3_noun viz; + + viz = u3nc(u3k(i_vir), u3k(u3h(u3t(nez)))); + cor = u3k(u3t(u3t(nez))); + + u3z(vir); + u3z(nez); + + return u3nt(u3_blip, viz, cor); + } + } + } +} + +/* _cv_spat(): spat with toy. +*/ +static u3_noun +_cv_spat(u3_noun pox) +{ + return u3_do("spat", pox); +} + +/* _cv_nock_poke(): call poke through hardcoded interface. +*/ +static u3_noun +_cv_nock_poke(u3_noun ovo) +{ + u3_noun fun = u3_cn_nock_on(u3k(u3A->roc), u3k(u3_cx_at(42, u3A->roc))); + u3_noun sam, pro; + + sam = u3nc(u3k(u3A->now), ovo); +#if 1 + { + c3_c* ovi_c = u3_cr_string(u3h(u3t(ovo))); + u3_noun tox = _cv_spat(u3k(u3h(ovo))); + c3_c* tox_c = u3_cr_string(tox); + + printf("poke: %%%s on %s\r\n", ovi_c, tox_c); + + free(tox_c); free(ovi_c); u3z(tox); + } +#endif + +#if 1 + { + c3_c* ovi_c = u3_cr_string(u3h(u3t(ovo))); + + printf("poked: %s\r\n", ovi_c); + + free(ovi_c); + } +#endif + + pro = u3_cn_slam_on(fun, sam); + return pro; +} + +/* _cv_nock_peek(): call peek through hardcoded interface. +*/ +static u3_noun +_cv_nock_peek(u3_noun hap) +{ + u3_noun fun = u3_cn_nock_on(u3k(u3A->roc), u3k(u3_cx_at(87, u3A->roc))); + u3_noun sam = u3nc(u3k(u3A->now), hap); + + return u3_cn_slam_on(fun, sam); +} + +/* _cv_nock_keep(): call wait through hardcoded interface. +*/ +static u3_noun +_cv_nock_keep(u3_noun hap) +{ + u3_noun fun = u3_cn_nock_on(u3k(u3A->roc), u3k(u3_cx_at(4, u3A->roc))); + u3_noun sam = u3nc(u3k(u3A->now), hap); + + return u3_cn_slam_on(fun, sam); +} + +/* u3_cv_do(): use a kernel function. +*/ +u3_noun +u3_cv_do(const c3_c* txt_c, u3_noun arg) +{ + printf("cv_do: fn %s\r\n", txt_c); + return u3_cn_slam_on(u3_cv_gate(txt_c), arg); +} + +/* u3_cv_wish(): noun from expression +*/ +u3_noun +u3_cv_wish(c3_c* str_c) +{ + return _cv_nock_wish(u3_ci_string(str_c)); +} + +/* _cv_scot(): print atom. +*/ +static u3_noun +_cv_scot(u3_noun dim) +{ + return u3_do("scot", dim); +} + +/* u3_cv_time(): set the reck time. +*/ +void +u3_cv_time(u3_noun now) +{ + u3z(u3A->now); + u3A->now = now; + + u3z(u3A->wen); + u3A->wen = _cv_scot(u3nc(c3__da, u3k(u3A->now))); +} + +/* u3_cv_numb(): set the instance number. +*/ +void +u3_cv_numb() +{ + u3A->sev_l = u3_cr_mug(u3A->now); + u3z(u3A->sen); + u3A->sen = _cv_scot(u3nc(c3__uv, u3A->sev_l)); +} + +#if 0 +/* _cv_time_bump(): advance the reck time by a small increment. +*/ +static void +_cv_time_bump(u3_reck* rec_u) +{ + c3_d bum_d = (1ULL << 48ULL); + + u3A->now = u3_cka_add(u3A->now, u3_ci_chubs(1, &bum_d)); +} +#endif + +/* u3_cv_peek(): query the reck namespace (protected). +*/ +u3_noun +u3_cv_peek(u3_noun hap) +{ + return _cv_nock_peek(hap); +} + +/* u3_cv_keep(): measure timer. +*/ +u3_noun +u3_cv_keep(u3_noun hap) +{ + return _cv_nock_keep(hap); +} + +#if 0 +/* _cv_mole(): parse simple atomic mole. +*/ +static u3_bean +_cv_mole(u3_noun fot, + u3_noun san, + c3_d* ato_d) +{ + u3_noun uco = u3_do("slay", san); + u3_noun p_uco, q_uco, r_uco, s_uco; + + if ( (u3_no == u3_cr_qual(uco, &p_uco, &q_uco, &r_uco, &s_uco)) || + (0 != p_uco) || + (0 != q_uco) || + (u3_no == u3_sing(fot, r_uco)) ) + { + uL(fprintf(uH, "strange mole %s\n", u3_cr_string(san))); + + u3z(fot); u3z(uco); return u3_no; + } + else { + *ato_d = u3_cr_chub(0, s_uco); + + u3z(fot); u3z(uco); return u3_yes; + } +} + +/* _cv_lily(): parse little atom. +*/ +static u3_bean +_cv_lily(u3_noun fot, u3_noun txt, c3_l* tid_l) +{ + c3_d ato_d; + + if ( u3_no == _cv_mole(fot, txt, &ato_d) ) { + return u3_no; + } else { + if ( ato_d >= 0x80000000ULL ) { + return u3_no; + } else { + *tid_l = (c3_l) ato_d; + + return u3_yes; + } + } +} +#endif + +/* u3_cv_poke(): insert and apply an input ovum (protected). +*/ +u3_noun +u3_cv_poke(u3_noun ovo) +{ + return _cv_nock_poke(ovo); +} + +/* u3_cv_http_request(): hear http request on channel (unprotected). +*/ +void +u3_cv_http_request(u3_bean sec, u3_noun pox, u3_noun req) +{ + // uL(fprintf(uH, "http: request\n")); + u3_cv_plan(pox, u3nq(c3__this, sec, 0, req)); +} + +/* _cv_tape(): dump a tape, old style. Don't do this. +*/ +static void +_cv_tape(FILE* fil_u, u3_noun tep) +{ + u3_noun tap = tep; + + while ( u3_nul != tap ) { + c3_c car_c; + + if ( u3h(tap) >= 127 ) { + car_c = '?'; + } else car_c = u3h(tap); + + putc(car_c, fil_u); + tap = u3t(tap); + } + u3z(tep); +} + +/* _cv_wall(): dump a wall, old style. Don't do this. +*/ +static void +_cv_wall(u3_noun wol) +{ + FILE* fil_u = stdout; + u3_noun wal = wol; + + while ( u3_nul != wal ) { + _cv_tape(fil_u, u3k(u3h(wal))); + + putc(13, fil_u); + putc(10, fil_u); + + wal = u3t(wal); + } + u3z(wol); +} + +/* u3_cv_tank(): dump single tank. +*/ +void +u3_cv_tank(u3_noun blu, c3_l tab_l, u3_noun tac) +{ + u3_cv_punt(blu, tab_l, u3nc(tac, u3_nul)); +} + +/* u3_cv_punt(): dump tank list. +*/ +void +u3_cv_punt(u3_noun blu, c3_l tab_l, u3_noun tac) +{ +#if 0 + u3_noun blu = u3_term_get_blew(0); +#endif + c3_l col_l = u3h(blu); + u3_noun cat = tac; + + // We are calling nock here, but hopefully need no protection. + // + while ( u3_yes == u3_cr_du(cat) ) { + u3_noun wol = u3_dc("wash", u3nc(tab_l, col_l), u3k(u3h(cat))); + + _cv_wall(wol); + cat = u3t(cat); + } + u3z(tac); + u3z(blu); +} + +/* u3_cv_sway(): print trace. +*/ +void +u3_cv_sway(u3_noun blu, c3_l tab_l, u3_noun tax) +{ + u3_noun mok = u3_dc("mook", 2, tax); + + u3_cv_punt(blu, tab_l, u3k(u3t(mok))); + u3z(mok); +} + +/* u3_cv_plan(): queue ovum (external). +*/ +void +u3_cv_plan(u3_noun pax, u3_noun fav) +{ + u3_noun egg = u3nc(pax, fav); + u3A->roe = u3nc(u3nc(u3_nul, egg), u3A->roe); +} + +/* u3_cv_plow(): queue multiple ova (external). +*/ +void +u3_cv_plow(u3_noun ova) +{ + u3_noun ovi = ova; + + while ( u3_nul != ovi ) { + u3_noun ovo=u3h(ovi); + + u3_cv_plan(u3k(u3h(ovo)), u3k(u3t(ovo))); + ovi = u3t(ovi); + } + u3z(ova); +} + +/* u3_cv_louse(): last-minute deviltry upon a bail. +*/ +void +u3_cv_louse(c3_m how_m) +{ +#if 0 + if ( c3__exit == how_m ) { + printf("louse: nocks: %d\n", NOX); + printf("louse: washing kernel %x %d\n", u3A->ken, u3_co_is_dog(u3A->ken)); + u3_cm_wash(u3A->ken); + + printf("kernel %x; washed mug %x\n", u3A->ken, u3_cr_mug(u3A->ken)); + } +#endif +} diff --git a/include/all.h b/include/all.h index 61d2a0f842..7f77a7acc7 100644 --- a/include/all.h +++ b/include/all.h @@ -48,6 +48,7 @@ **/ # include "n/tune.h" # include "n/noun.h" +# include "n/save.h" # include "n/hash.h" # include "n/road.h" # include "n/jets.h" @@ -58,6 +59,7 @@ /** g: the u3 layer, functions. **/ # include "g/a.h" +# include "g/e.h" # include "g/h.h" # include "g/i.h" # include "g/j.h" diff --git a/include/g/e.h b/include/g/e.h index 660063958c..614ce4af97 100644 --- a/include/g/e.h +++ b/include/g/e.h @@ -6,19 +6,15 @@ **/ /* u3_ce_fault(): handle a memory event with libsigsegv protocol. */ - static c3_i + c3_i u3_ce_fault(void* adr_v, c3_i ser_i); - /* u3_ce_load(): try to load image from checkpoint directory. + /* u3_ce_save(): */ - u3_o - u3_ce_load(const c3_c* pax_c, c3_p adr_p, c3_w len_w) + void + u3_ce_save(void); - /* u3_ce_make(): create new image with checkpoint. + /* u3_ce_boot(): start the memory system. */ - u3_o - u3_ce_make(const c3_c* pax_c); - - /* u3_ce_sync(): save changes with checkpoint dir. - */ - u3_ce_sync(void); + void + u3_ce_boot(c3_c* cpu_c); diff --git a/include/g/m.h b/include/g/m.h index cdba7c4ab9..029c2407a6 100644 --- a/include/g/m.h +++ b/include/g/m.h @@ -4,10 +4,10 @@ */ /** System management. **/ - /* u3_cm_boot(): make u3R and u3H from `len` words at `adr`. + /* u3_cm_boot(): set up top-level road. */ void - u3_cm_boot(c3_p adr_p, c3_w len_w); + u3_cm_boot(); /* u3_cm_trap(): setjmp within road. */ diff --git a/include/g/v.h b/include/g/v.h new file mode 100644 index 0000000000..5210484939 --- /dev/null +++ b/include/g/v.h @@ -0,0 +1,107 @@ +/* include/g/v.h +** +** This file is in the public domain. +*/ + /** Arvo macros. + **/ +# define u3_do(txt_c, arg) u3_cv_do(txt_c, arg) +# define u3_dc(txt_c, a, b) u3_cv_do(txt_c, u3nc(a, b)) +# define u3_dt(txt_c, a, b, c) u3_cv_do(txt_c, u3nt(a, b, c)) +# define u3_dq(txt_c, a, b, c, d) u3_cv_do(txt_c, u3nt(a, b, c, d)) + + /** Arvo functions. Rather unstructured. + **/ + /* u3_cv_do(): use a kernel function. + */ + u3_noun + u3_cv_do(const c3_c* txt_c, u3_noun arg); + + /* u3_cv_make(): make a new pier by loading a pill. + */ + void + u3_cv_make(c3_c* pas_c, u3_noun now); + + /* u3_cv_gate(): load a kernel function. + */ + u3_noun + u3_cv_gate(const c3_c* txt_c); + + /* u3_cv_pike(): poke with floating core. + */ + u3_noun + u3_cv_pike(u3_noun ovo, u3_noun cor); + + /* u3_cv_nick(): transform enveloped packets, [vir cor]. + */ + u3_noun + u3_cv_nick(u3_noun vir, u3_noun cor); + + /* u3_cv_do(): use a kernel function. + */ + u3_noun + u3_cv_do(const c3_c* txt_c, u3_noun arg); + + /* u3_cv_wish(): noun from expression. + */ + u3_noun + u3_cv_wish(c3_c* str_c); + + /* u3_cv_numb(): set the instance number. + */ + void + u3_cv_numb(void); + + /* u3_cv_time(): set the reck time. + */ + void + u3_cv_time(u3_noun now); + + /* u3_cv_peek(): query the reck namespace. + */ + u3_noun + u3_cv_peek(u3_noun hap); + + /* u3_cv_keep(): measure timer. + */ + u3_noun + u3_cv_keep(u3_noun hap); + + /* u3_cv_poke(): insert and apply an input ovum (protected). + */ + u3_noun + u3_cv_poke(u3_noun ovo); + + /* u3_cv_http_request(): hear http request on channel (unprotected). + */ + void + u3_cv_http_request(u3_bean sec, u3_noun pox, u3_noun req); + + /* u3_cv_tank(): dump single tank. + */ + void + u3_cv_tank(u3_noun blu, c3_l tab_l, u3_noun tac); + + /* u3_cv_punt(): dump tank list. + */ + void + u3_cv_punt(u3_noun blu, c3_l tab_l, u3_noun tac); + + /* u3_cv_sway(): print trace. + */ + void + u3_cv_sway(u3_noun blu, c3_l tab_l, u3_noun tax); + + /* u3_cv_plan(): queue ovum (external). + */ + void + u3_cv_plan(u3_noun pax, u3_noun fav); + + /* u3_cv_plow(): queue multiple ova (external). + */ + void + u3_cv_plow(u3_noun ova); + + /* u3_cv_louse(): last-minute deviltry upon a bail. + */ + void + u3_cv_louse(c3_m how_m); diff --git a/include/n/arvo.h b/include/n/arvo.h index af72831e07..2231469212 100644 --- a/include/n/arvo.h +++ b/include/n/arvo.h @@ -19,6 +19,7 @@ /* u3_cs_arvo: modern arvo structure. */ typedef struct _u3_cs_arvo { + c3_d ent_d; // event number u3_noun yot; // cached gates u3_noun now; // current time, as noun u3_noun wen; // current time, as text diff --git a/include/n/glob.h b/include/n/glob.h index 80817eb6f0..fae8cd79fa 100644 --- a/include/n/glob.h +++ b/include/n/glob.h @@ -2,6 +2,16 @@ ** ** This file is in the public domain. */ + /** Data structures. + **/ + /* u3_cs_home: all internal (within image) state. + */ + typedef struct _u3_cs_home { + u3_cs_road rod_u; // storage state + u3_cs_arvo arv_u; // arvo state + } u3_cs_home; + + /** Globals. **/ /* u3_Loom: base of loom, as a word pointer. @@ -26,7 +36,7 @@ /* u3_Pool / u3P: global memory control. */ - extern u3_cs_pool u3_Pool; + c3_global u3_cs_pool u3_Pool; # define u3P u3_Pool /* u3_Code: memory code. diff --git a/include/n/save.h b/include/n/save.h new file mode 100644 index 0000000000..63e0e71248 --- /dev/null +++ b/include/n/save.h @@ -0,0 +1,49 @@ +/* include/n/save.h +** +** This file is in the public domain. +*/ + /** Data structures. + **/ + /* u3_cs_line: control line. + */ + typedef struct _u3_cs_line { + c3_w pag_w; + c3_w mug_w; + } u3_cs_line; + + /* u3_cs_control: memory change, control file. + */ + typedef struct _u3_cs_control { + c3_d evt_d; // event number + c3_w nor_w; // new page count north + c3_w sou_w; // new page count south + c3_w pgs_w; // number of changed pages + u3_cs_line mem_u[0]; // per page + } u3_cs_control; + + /* u3_cs_patch: memory change, top level. + */ + typedef struct _u3_cs_patch { + c3_i ctl_i; + c3_i mem_i; + u3_cs_control* con_u; + } u3_cs_patch; + + /* u3_cs_image: memory segment, open file. + */ + typedef struct _u3_cs_image { + c3_c* nam_c; // segment name + c3_i fid_i; // open file, or 0 + c3_w pgs_w; // length in pages + } u3_cs_image; + + /* u3_cs_pool: entire memory system. + */ + typedef struct _u3_cs_pool { + c3_c* cpu_c; // path to + c3_d evt_d; // last patch written at event + c3_w dit_w[u3_cc_pages >> 5]; // touched since last save + u3_cs_image nor_u; // north segment + u3_cs_image sou_u; // south segment + } u3_cs_pool; + diff --git a/outside/jhttp/http_parser.c b/outside/jhttp/http_parser.c index 9474340885..653d0331f5 100755 --- a/outside/jhttp/http_parser.c +++ b/outside/jhttp/http_parser.c @@ -1894,13 +1894,15 @@ http_parser_init (http_parser *parser, enum http_parser_type t) const char * http_errno_name(enum http_errno err) { - assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); + // this assert is statically true, making the compiler complain + // assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].name; } const char * http_errno_description(enum http_errno err) { - assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); + // this assert is statically true, making the compiler complain + // assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0]))); return http_strerror_tab[err].description; } diff --git a/v/main.c b/v/main.c index d683b18903..0e527336be 100644 --- a/v/main.c +++ b/v/main.c @@ -265,15 +265,19 @@ main(c3_i argc, printf("Starting daemon\n"); } - // Seed prng. Don't panic -- just for fuzz testing and election timeouts. + // Seed prng. Don't panic -- just for fuzz testing. // srand(getpid()); // Instantiate process globals. { - /* Boot memory. + /* Boot the image and checkpoint. */ - u3_cm_boot(U2_OS_LoomBase, (1 << U2_OS_LoomBits)); + u3_ce_boot(u3_Host.cpu_c); + + /* Boot the allocator. + */ + u3_cm_boot(); /* Boot jets. */