diff --git a/pkg/urbit/bench/ur_bench.c b/pkg/urbit/bench/ur_bench.c index 40a4e518c6..5ede7b5e92 100644 --- a/pkg/urbit/bench/ur_bench.c +++ b/pkg/urbit/bench/ur_bench.c @@ -7,7 +7,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 23); u3m_pave(c3y); } diff --git a/pkg/urbit/include/noun/allocate.h b/pkg/urbit/include/noun/allocate.h index 529ad6fb60..964de538be 100644 --- a/pkg/urbit/include/noun/allocate.h +++ b/pkg/urbit/include/noun/allocate.h @@ -1,8 +1,6 @@ #ifndef U3_ALLOCATE_H #define U3_ALLOCATE_H -#include - #include "manage.h" /** Constants. @@ -15,15 +13,15 @@ */ # define u3a_page 12 - /* u3a_pages: number of pages in memory. + /* u3a_pages: maximum number of pages in memory. */ # define u3a_pages (1 << (u3a_bits - u3a_page)) - /* u3a_words: number of words in memory. + /* u3a_words: maximum number of words in memory. */ # define u3a_words (1 << u3a_bits) - /* u3a_bytes: number of bytes in memory. + /* u3a_bytes: maximum number of bytes in memory. */ # define u3a_bytes (sizeof(c3_w) * u3a_words) @@ -477,15 +475,6 @@ void* u3a_malloc(size_t len_i); - /* u3a_malloc_ssl(): openssl-shaped malloc - */ - void* - u3a_malloc_ssl(size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ); - /* u3a_calloc(): aligned storage measured in bytes. */ void* @@ -496,39 +485,11 @@ void* u3a_realloc(void* lag_v, size_t len_i); - /* u3a_realloc2(): gmp-shaped realloc. - */ - void* - u3a_realloc2(void* lag_v, size_t old_i, size_t new_i); - - /* u3a_realloc_ssl(): openssl-shaped realloc. - */ - void* - u3a_realloc_ssl(void* lag_v, size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ); - /* u3a_free(): free for aligned malloc. */ void u3a_free(void* tox_v); - /* u3a_free2(): gmp-shaped free. - */ - void - u3a_free2(void* tox_v, size_t siz_i); - - /* u3a_free_ssl(): openssl-shaped free. - */ - void - u3a_free_ssl(void* tox_v -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ); - /* Reference and arena control. */ /* u3a_gain(): gain a reference count in normal space. diff --git a/pkg/urbit/include/noun/events.h b/pkg/urbit/include/noun/events.h index 92d5c2a75e..4a27959634 100644 --- a/pkg/urbit/include/noun/events.h +++ b/pkg/urbit/include/noun/events.h @@ -41,6 +41,7 @@ typedef struct _u3e_pool { c3_c* dir_c; // path to c3_w dit_w[u3a_pages >> 5]; // touched since last save + c3_w pag_w; // number of pages (<= u3a_pages) u3e_image nor_u; // north segment u3e_image sou_u; // south segment } u3e_pool; diff --git a/pkg/urbit/include/noun/manage.h b/pkg/urbit/include/noun/manage.h index 89f50d6037..a1ffb6495d 100644 --- a/pkg/urbit/include/noun/manage.h +++ b/pkg/urbit/include/noun/manage.h @@ -37,7 +37,7 @@ /* u3m_init(): start the environment. */ void - u3m_init(); + u3m_init(size_t len_i); /* u3m_pave(): instantiate or activate image. */ diff --git a/pkg/urbit/include/noun/options.h b/pkg/urbit/include/noun/options.h index f73dba264d..c1fd58c408 100644 --- a/pkg/urbit/include/noun/options.h +++ b/pkg/urbit/include/noun/options.h @@ -9,6 +9,7 @@ u3_noun who; // single identity c3_c* dir_c; // execution directory (pier) c3_w wag_w; // flags (both ways) + size_t wor_i; // loom word-length (<= u3a_words) void (*stderr_log_f)(c3_c*); // errors from c code void (*slog_f)(u3_noun); // function pointer for slog void (*sign_hold_f)(void); // suspend system signal regime diff --git a/pkg/urbit/noun/allocate.c b/pkg/urbit/noun/allocate.c index 2a92e64903..f7ce679584 100644 --- a/pkg/urbit/noun/allocate.c +++ b/pkg/urbit/noun/allocate.c @@ -692,18 +692,6 @@ u3a_malloc(size_t len_i) return out_w; } -/* u3a_malloc_ssl(): openssl-shaped malloc -*/ -void* -u3a_malloc_ssl(size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ) -{ - return u3a_malloc(len_i); -} - /* u3a_cellblock(): allocate a block of cells on the hat. */ static c3_o @@ -885,26 +873,6 @@ u3a_realloc(void* lag_v, size_t len_i) return u3a_wealloc(lag_v, (len_w + 3) >> 2); } -/* u3a_realloc2(): gmp-shaped realloc. -*/ -void* -u3a_realloc2(void* lag_v, size_t old_i, size_t new_i) -{ - return u3a_realloc(lag_v, new_i); -} - -/* u3a_realloc_ssl(): openssl-shaped realloc. -*/ -void* -u3a_realloc_ssl(void* lag_v, size_t len_i -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ) -{ - return u3a_realloc(lag_v, len_i); -} - /* u3a_free(): free for aligned malloc. */ void @@ -921,26 +889,6 @@ u3a_free(void* tox_v) u3a_wfree(org_w); } -/* u3a_free2(): gmp-shaped free. -*/ -void -u3a_free2(void* tox_v, size_t siz_i) -{ - return u3a_free(tox_v); -} - -/* u3a_free_ssl(): openssl-shaped free. -*/ -void -u3a_free_ssl(void* tox_v -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - , const char* file, int line -#endif - ) -{ - return u3a_free(tox_v); -} - /* _me_wash_north(): clean up mug slots after copy. */ static void _me_wash_north(u3_noun dog); diff --git a/pkg/urbit/noun/events.c b/pkg/urbit/noun/events.c index 6986e91a22..601e803c3c 100644 --- a/pkg/urbit/noun/events.c +++ b/pkg/urbit/noun/events.c @@ -136,9 +136,9 @@ u3e_check(c3_c* cap_c) sum_w += mug_w; } for ( i_w = 0; i_w < sou_w; i_w++ ) { - mug_w = _ce_check_page((u3a_pages - (i_w + 1))); + mug_w = _ce_check_page((u3P.pag_w - (i_w + 1))); if ( strcmp(cap_c, "boot") ) { - c3_assert(mug_w == u3K.mug_w[(u3a_pages - (i_w + 1))]); + c3_assert(mug_w == u3K.mug_w[(u3P.pag_w - (i_w + 1))]); } sum_w += mug_w; } @@ -195,7 +195,7 @@ _ce_center_guard_page(void) { u3p(c3_w) bot_p, top_p; if ( !u3R ) { - top_p = u3a_outa(u3_Loom + u3a_words); + top_p = u3a_outa(u3_Loom + u3C.wor_i); bot_p = u3a_outa(u3_Loom); } else if ( c3y == u3a_is_north(u3R) ) { @@ -255,9 +255,9 @@ u3e_fault(void* adr_v, c3_i ser_i) c3_w* adr_w = (c3_w*) adr_v; - if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3a_words)) ) { + if ( (adr_w < u3_Loom) || (adr_w >= (u3_Loom + u3C.wor_i)) ) { fprintf(stderr, "address %p out of loom!\r\n", adr_w); - fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3a_words); + fprintf(stderr, "loom: [%p : %p)\r\n", u3_Loom, u3_Loom + u3C.wor_i); c3_assert(0); return 0; } @@ -629,7 +629,7 @@ _ce_patch_compose(void) pgs_w = _ce_patch_count_page(i_w, pgs_w); } for ( i_w = 0; i_w < sou_w; i_w++ ) { - pgs_w = _ce_patch_count_page((u3a_pages - (i_w + 1)), pgs_w); + pgs_w = _ce_patch_count_page((u3P.pag_w - (i_w + 1)), pgs_w); } } @@ -649,7 +649,7 @@ _ce_patch_compose(void) 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, (u3a_pages - (i_w + 1)), pgc_w); + pgc_w = _ce_patch_save_page(pat_u, (u3P.pag_w - (i_w + 1)), pgc_w); } pat_u->con_u->nor_w = nor_w; @@ -699,7 +699,7 @@ _ce_image_resize(u3e_image* img_u, c3_w pgs_w) { if ( img_u->pgs_w > pgs_w ) { if ( ftruncate(img_u->fid_i, pgs_w << (u3a_page + 2)) ) { - fprintf(stderr, "loom: image truncate %s: %s\r\n", + fprintf(stderr, "loom: image (%s) truncate: %s\r\n", img_u->nam_c, strerror(errno)); c3_assert(0); @@ -745,7 +745,7 @@ _ce_patch_apply(u3_ce_patch* pat_u) } else { fid_i = u3P.sou_u.fid_i; - off_w = (u3a_pages - (pag_w + 1)); + off_w = (u3P.pag_w - (pag_w + 1)); } if ( -1 == read(pat_u->mem_i, mem_w, pag_siz_i) ) { @@ -785,7 +785,8 @@ _ce_image_blit(u3e_image* img_u, 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, siz_w) ) { - fprintf(stderr, "loom: image blit read: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) blit read: %s\r\n", + img_u->nam_c, strerror(errno)); c3_assert(0); } @@ -819,7 +820,9 @@ _ce_image_fine(u3e_image* img_u, c3_w mem_w, fil_w; if ( -1 == read(img_u->fid_i, buf_w, pag_siz_i) ) { - fprintf(stderr, "loom: image fine read: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) fine read: %s\r\n", + img_u->nam_c, + strerror(errno)); c3_assert(0); } mem_w = u3r_mug_words(ptr_w, pag_wiz_i); @@ -828,11 +831,13 @@ _ce_image_fine(u3e_image* img_u, if ( mem_w != fil_w ) { c3_w pag_w = (ptr_w - u3_Loom) >> u3a_page; - fprintf(stderr, "mismatch: page %d, mem_w %x, fil_w %x, K %x\r\n", - pag_w, - mem_w, - fil_w, - u3K.mug_w[pag_w]); + fprintf(stderr, "loom: image (%s) mismatch: " + "page %d, mem_w %x, fil_w %x, K %x\r\n", + img_u->nam_c, + pag_w, + mem_w, + fil_w, + u3K.mug_w[pag_w]); abort(); } ptr_w += stp_ws; @@ -856,7 +861,9 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) if ( (-1 == lseek(fom_u->fid_i, 0, SEEK_SET)) || (-1 == lseek(tou_u->fid_i, 0, SEEK_SET)) ) { - fprintf(stderr, "loom: image copy seek 0: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy seek: %s\r\n", + fom_u->nam_c, + strerror(errno)); return c3n; } @@ -867,16 +874,22 @@ _ce_image_copy(u3e_image* fom_u, u3e_image* tou_u) c3_w off_w = i_w; if ( -1 == read(fom_u->fid_i, mem_w, pag_siz_i) ) { - fprintf(stderr, "loom: image copy read: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy read: %s\r\n", + fom_u->nam_c, + strerror(errno)); return c3n; } else { if ( -1 == lseek(tou_u->fid_i, (off_w << (u3a_page + 2)), SEEK_SET) ) { - fprintf(stderr, "loom: image copy seek: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy seek: %s\r\n", + tou_u->nam_c, + strerror(errno)); return c3n; } if ( -1 == write(tou_u->fid_i, mem_w, pag_siz_i) ) { - fprintf(stderr, "loom: image copy write: %s\r\n", strerror(errno)); + fprintf(stderr, "loom: image (%s) copy write: %s\r\n", + tou_u->nam_c, + strerror(errno)); return c3n; } } @@ -983,7 +996,7 @@ u3e_save(void) pag_wiz_i); _ce_image_fine(&u3P.sou_u, - (u3_Loom + (1 << u3a_bits) - pag_wiz_i), + (u3_Loom + u3C.wor_i) - pag_wiz_i, -(ssize_t)pag_wiz_i); c3_assert(u3P.nor_u.pgs_w == u3K.nor_w); @@ -1011,6 +1024,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) u3P.dir_c = dir_c; u3P.nor_u.nam_c = "north"; u3P.sou_u.nam_c = "south"; + u3P.pag_w = u3C.wor_i >> u3a_page; // XX review dryrun requirements, enable or remove // @@ -1041,6 +1055,11 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) _ce_patch_delete(); } + if ( u3P.nor_u.pgs_w + u3P.sou_u.pgs_w >= u3P.pag_w ) { + fprintf(stderr, "boot: snapshot too big for loom\r\n"); + exit(1); + } + // mark all pages dirty (pages in the snapshot will be marked clean) // u3e_foul(); @@ -1053,7 +1072,7 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) pag_wiz_i); _ce_image_blit(&u3P.sou_u, - (u3_Loom + (1 << u3a_bits) - pag_wiz_i), + (u3_Loom + u3C.wor_i) - pag_wiz_i, -(ssize_t)pag_wiz_i); u3l_log("boot: protected loom\r\n"); @@ -1080,9 +1099,12 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) c3_o u3e_yolo(void) { - // NB: u3e_save() will reinstate protection flags + // NB: u3e_save() will reinstate protection flags // - if ( 0 != mprotect((void *)u3_Loom, u3a_bytes, (PROT_READ | PROT_WRITE)) ) { + if ( 0 != mprotect((void *)u3_Loom, + u3C.wor_i << 2, + (PROT_READ | PROT_WRITE)) ) + { return c3n; } @@ -1100,6 +1122,8 @@ u3e_foul(void) void u3e_init(void) { + u3P.pag_w = u3C.wor_i >> u3a_page; + #ifdef U3_GUARD_PAGE _ce_center_guard_page(); #endif diff --git a/pkg/urbit/noun/manage.c b/pkg/urbit/noun/manage.c index 17befccf70..26f103fa70 100644 --- a/pkg/urbit/noun/manage.c +++ b/pkg/urbit/noun/manage.c @@ -553,7 +553,7 @@ _pave_home(void) { c3_w* mem_w = u3_Loom + 1; c3_w siz_w = c3_wiseof(u3v_home); - c3_w len_w = u3a_words - 1; + c3_w len_w = u3C.wor_i - 1; u3H = (void *)_pave_north(mem_w, siz_w, len_w); u3H->ver_w = u3v_version; @@ -574,7 +574,7 @@ _find_home(void) // c3_w* mem_w = u3_Loom + 1; c3_w siz_w = c3_wiseof(u3v_home); - c3_w len_w = u3a_words - 1; + c3_w len_w = u3C.wor_i - 1; { c3_w ver_w = *((mem_w + len_w) - 1); @@ -590,6 +590,11 @@ _find_home(void) u3H = (void *)((mem_w + len_w) - siz_w); u3R = &u3H->rod_u; + + // this looks risky, but there are no legitimate scenarios + // where it's wrong + // + u3R->cap_p = u3R->mat_p = u3C.wor_i - c3_wiseof(*u3H); } /* u3m_pave(): instantiate or activate image. @@ -1718,16 +1723,53 @@ _cm_signals(void) # endif } -extern void u3je_secp_init(void); -extern void u3je_secp_stop(void); +/* _cm_malloc_ssl(): openssl-shaped malloc +*/ +static void* +_cm_malloc_ssl(size_t len_i +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + , const char* file, int line +#endif + ) +{ + return u3a_malloc(len_i); +} +/* _cm_realloc_ssl(): openssl-shaped realloc. +*/ +static void* +_cm_realloc_ssl(void* lag_v, size_t len_i +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + , const char* file, int line +#endif + ) +{ + return u3a_realloc(lag_v, len_i); +} + +/* _cm_free_ssl(): openssl-shaped free. +*/ +static void +_cm_free_ssl(void* tox_v +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + , const char* file, int line +#endif + ) +{ + return u3a_free(tox_v); +} + +extern void u3je_secp_init(void); + +/* _cm_crypto(): initialize openssl and crypto jets. +*/ static void _cm_crypto() { /* Initialize OpenSSL with loom allocation functions. */ - if ( 0 == CRYPTO_set_mem_functions(&u3a_malloc_ssl, - &u3a_realloc_ssl, - &u3a_free_ssl) ) { + if ( 0 == CRYPTO_set_mem_functions(&_cm_malloc_ssl, + &_cm_realloc_ssl, + &_cm_free_ssl) ) { u3l_log("%s\r\n", "openssl initialization failed"); abort(); } @@ -1735,53 +1777,81 @@ _cm_crypto() u3je_secp_init(); } +/* _cm_realloc2(): gmp-shaped realloc. +*/ +static void* +_cm_realloc2(void* lag_v, size_t old_i, size_t new_i) +{ + return u3a_realloc(lag_v, new_i); +} + +/* _cm_free2(): gmp-shaped free. +*/ +static void +_cm_free2(void* tox_v, size_t siz_i) +{ + return u3a_free(tox_v); +} + /* u3m_init(): start the environment. */ void -u3m_init(void) +u3m_init(size_t len_i) { _cm_limits(); _cm_signals(); _cm_crypto(); - /* Make sure GMP uses our malloc. - */ - mp_set_memory_functions(u3a_malloc, u3a_realloc2, u3a_free2); + // make sure GMP uses our malloc. + // + mp_set_memory_functions(u3a_malloc, _cm_realloc2, _cm_free2); - /* Map at fixed address. - */ + // make sure that [len_i] is a fully-addressible non-zero power of two. + // + if ( !len_i + || (len_i & (len_i - 1)) + || (len_i < (1 << (u3a_page + 2))) + || (len_i > u3a_bytes) ) { - c3_w len_w = u3a_bytes; - void* map_v; + u3l_log("loom: bad size: %zu\r\n", len_i); + exit(1); + } - map_v = mmap((void *)u3_Loom, - len_w, - (PROT_READ | PROT_WRITE), - (MAP_ANON | MAP_FIXED | MAP_PRIVATE), - -1, 0); + // map at fixed address. + // + { + void* map_v = mmap((void *)u3_Loom, + len_i, + (PROT_READ | PROT_WRITE), + (MAP_ANON | MAP_FIXED | MAP_PRIVATE), + -1, 0); if ( -1 == (c3_ps)map_v ) { - void* dyn_v = mmap((void *)0, - len_w, - PROT_READ, - MAP_ANON | MAP_PRIVATE, - -1, 0); + map_v = mmap((void *)0, + len_i, + (PROT_READ | PROT_WRITE), + (MAP_ANON | MAP_PRIVATE), + -1, 0); - u3l_log("boot: mapping %dMB failed\r\n", (len_w / (1024 * 1024))); + u3l_log("boot: mapping %zuMB failed\r\n", len_i >> 20); u3l_log("see urbit.org/using/install/#about-swap-space" " for adding swap space\r\n"); - if ( -1 != (c3_ps)dyn_v ) { + if ( -1 != (c3_ps)map_v ) { u3l_log("if porting to a new platform, try U3_OS_LoomBase %p\r\n", - dyn_v); + map_v); } exit(1); } - u3l_log("loom: mapped %dMB\r\n", len_w >> 20); + u3C.wor_i = len_i >> 2; + u3l_log("loom: mapped %zuMB\r\n", len_i >> 20); } } -/* u3m_stop(): graceful shutdown cleanup. */ +extern void u3je_secp_stop(void); + +/* u3m_stop(): graceful shutdown cleanup. +*/ void u3m_stop() { @@ -1797,7 +1867,7 @@ u3m_boot(c3_c* dir_c) /* Activate the loom. */ - u3m_init(); + u3m_init(u3a_bytes); /* Activate the storage system. */ @@ -1847,7 +1917,7 @@ u3m_boot_lite(void) { /* Activate the loom. */ - u3m_init(); + u3m_init(u3a_bytes); /* Activate tracing. */ diff --git a/pkg/urbit/tests/ames_tests.c b/pkg/urbit/tests/ames_tests.c index 69ed7b9b98..0907898d41 100644 --- a/pkg/urbit/tests/ames_tests.c +++ b/pkg/urbit/tests/ames_tests.c @@ -6,7 +6,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 22); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/hashtable_tests.c b/pkg/urbit/tests/hashtable_tests.c index 6322a331cc..3b36dc8876 100644 --- a/pkg/urbit/tests/hashtable_tests.c +++ b/pkg/urbit/tests/hashtable_tests.c @@ -9,7 +9,7 @@ c3_w _ch_skip_slot(c3_w mug_w, c3_w lef_w); static void _setup(void) { - u3m_init(); + u3m_init(1 << 26); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/jam_tests.c b/pkg/urbit/tests/jam_tests.c index eebc27fc1f..38e1494edc 100644 --- a/pkg/urbit/tests/jam_tests.c +++ b/pkg/urbit/tests/jam_tests.c @@ -6,7 +6,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 23); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/jet_tests.c b/pkg/urbit/tests/jet_tests.c index 2e96f2305f..4904a959da 100644 --- a/pkg/urbit/tests/jet_tests.c +++ b/pkg/urbit/tests/jet_tests.c @@ -5,7 +5,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 20); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/mug_tests.c b/pkg/urbit/tests/mug_tests.c index 7ac9783d26..ffd0516747 100644 --- a/pkg/urbit/tests/mug_tests.c +++ b/pkg/urbit/tests/mug_tests.c @@ -5,7 +5,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 20); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/newt_tests.c b/pkg/urbit/tests/newt_tests.c index 043151784b..6fdbdb759e 100644 --- a/pkg/urbit/tests/newt_tests.c +++ b/pkg/urbit/tests/newt_tests.c @@ -6,7 +6,7 @@ static void _setup(void) { - u3m_init(); + u3m_init(1 << 20); u3m_pave(c3y); } diff --git a/pkg/urbit/tests/nock_tests.c b/pkg/urbit/tests/nock_tests.c index 19c7ef200d..a96ed09bd1 100644 --- a/pkg/urbit/tests/nock_tests.c +++ b/pkg/urbit/tests/nock_tests.c @@ -5,7 +5,10 @@ static void _setup(void) { - u3m_init(); + // XX at 1<<24, this succeeds on mac, but bail:exit's on linux. + // investigate possible u3n_prog corruption + // + u3m_init(1 << 25); u3m_pave(c3y); u3e_init(); }