Val _util_NetDB_mkservent (Task* task, struct servent* sentry) { //===================== // // Mythryl type: // // Allocate an Lib7 value of type: // Null_Or( (String, List(String), Int, String) ) // to represent a struct servent value. Note that the port number is returned // in network byteorder, so we need to map it to host order. if (sentry == NULL) return OPTION_NULL; // If our agegroup0 buffer is more than half full, // empty it by doing a heapcleaning. This is very // conservative -- which is the way I like it. :-) // if (agegroup0_freespace_in_bytes( task ) < agegroup0_usedspace_in_bytes( task ) ){ call_heapcleaner( task, 0 ); } // Build the return result: Val name = make_ascii_string_from_c_string__may_heapclean( task, sentry->s_name, NULL ); Roots roots1 = { &name, NULL }; Val aliases = make_ascii_strings_from_vector_of_c_strings__may_heapclean( task, sentry->s_aliases, &roots1); Roots roots2 = { &aliases, &roots1 }; Val proto = make_ascii_string_from_c_string__may_heapclean( task, sentry->s_proto, &roots2); // Roots roots3 = { &proto, &roots2 }; Val port = TAGGED_INT_FROM_C_INT( ntohs(sentry->s_port) ); Val result = make_four_slot_record(task, name, aliases, port, proto); return OPTION_THE( task, result ); }
Val _util_NetDB_mknetent (Task *task, struct netent* nentry) { //==================== // // Allocate a Mythryl value of type // Null_Or( (String, List(String), Addr_Family, Sysword) ) // to represent a struct netent value. if (nentry == NULL) return OPTION_NULL; // Build the return result: // If our agegroup0 buffer is more than half full, // empty it by doing a heapcleaning. This is very // conservative -- which is the way I like it. :-) // if (agegroup0_freespace_in_bytes( task ) < agegroup0_usedspace_in_bytes( task ) ){ call_heapcleaner( task, 0 ); } Val name = make_ascii_string_from_c_string__may_heapclean( task, nentry->n_name, NULL ); Roots roots1 = { &name, NULL }; Val aliases = make_ascii_strings_from_vector_of_c_strings__may_heapclean( task, nentry->n_aliases, &roots1 ); Roots roots2 = { &aliases, &roots1 }; Val af = make_system_constant__may_heapclean( task, &_Sock_AddrFamily, nentry->n_addrtype, &roots2 ); // Roots roots3 = { &af, &roots2 }; Val net = make_one_word_unt( task, (Vunt) (nentry->n_net) ); // Roots roots4 = { &net, &roots3 }; Val result = make_four_slot_record( task, name, aliases, af, net ); return OPTION_THE( task, result ); }
Val _lib7_netdb_get_protocol_by_number (Task* task, Val arg) { //================================== // // Mythryl type: Int -> Null_Or( (String, List(String), Int) ) // // This fn gets bound as get_prot_by_number' in: // // src/lib/std/src/socket/net-protocol-db.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); int number = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // struct protoent* pentry = getprotobynumber( number ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (pentry == NULL) return OPTION_NULL; Val name = make_ascii_string_from_c_string__may_heapclean (task, pentry->p_name, NULL ); Roots roots1 = { &name, NULL }; Val aliases = make_ascii_strings_from_vector_of_c_strings__may_heapclean(task, pentry->p_aliases, &roots1 ); Val result = make_three_slot_record( task, name, aliases, TAGGED_INT_FROM_C_INT(pentry->p_proto) ); result = OPTION_THE( task, result ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_netdb_get_protocol_by_name (Task* task, Val arg) { //================================ // // Mythryl type: String -> Null_Or( (String, List(String), Int) ) // // This fn gets bound as get_prot_by_name' in: // // src/lib/std/src/socket/net-protocol-db.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); struct protoent* pentry; char* heap_name = HEAP_STRING_AS_C_STRING( arg ); // Last use of 'arg'. // We cannot reference anything on the Mythryl // heap between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so copy heap_name into C storage: // Mythryl_Heap_Value_Buffer name_buf; // { char* c_name = buffer_mythryl_heap_value( &name_buf, (void*) heap_name, strlen( heap_name ) +1 ); // '+1' for terminal NUL on string. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // pentry = getprotobyname( c_name ); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); unbuffer_mythryl_heap_value( &name_buf ); } if (pentry == NULL) return OPTION_NULL; Val name = make_ascii_string_from_c_string__may_heapclean (task, pentry->p_name, NULL ); Roots roots1 = { &name, NULL }; Val aliases = make_ascii_strings_from_vector_of_c_strings__may_heapclean (task, pentry->p_aliases, &roots1 ); Val result = make_three_slot_record( task, name, aliases, TAGGED_INT_FROM_C_INT(pentry->p_proto) ); result = OPTION_THE( task, result ); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Task* import_heap_image__may_heapclean (const char* fname, Heapcleaner_Args* params, Roots* extra_roots) { // ================================ // // This fn is called (only) by load_and_run_heap_image__may_heapclean in src/c/main/load-and-run-heap-image.c // Task* task; Heapfile_Header image_header; Heap_Header heap_header; Val *externs; Pthread_Image image; Inbuf inbuf; if (fname != NULL) { // // Resolve the name of the image. // If the file exists use it, otherwise try the // pathname with the machine ID as an extension. if ((inbuf.file = fopen(fname, "rb"))) { // if (verbosity__global > 0) say("loading %s ", fname); } else { // if ((inbuf.file = fopen(fname, "rb"))) { // if (verbosity__global > 0) say("loading %s ", fname); } else { die ("unable to open heap image \"%s\"\n", fname); } } inbuf.needs_to_be_byteswapped = FALSE; inbuf.buf = NULL; inbuf.nbytes = 0; } else { // // fname == NULL, so try to find // an in-core heap image: #if defined(DLOPEN) && !defined(OPSYS_WIN32) // void *lib = dlopen (NULL, RTLD_LAZY); void *vimg, *vimglenptr; if ((vimg = dlsym(lib,HEAP_IMAGE_SYMBOL )) == NULL) die("no in-core heap image found\n"); if ((vimglenptr = dlsym(lib,HEAP_IMAGE_LEN_SYMBOL)) == NULL) die("unable to find length of in-core heap image\n"); inbuf.file = NULL; inbuf.needs_to_be_byteswapped = FALSE; inbuf.base = vimg; inbuf.buf = inbuf.base; inbuf.nbytes = *(long*)vimglenptr; #else die("in-core heap images not implemented\n"); #endif } READ(&inbuf, image_header); if (image_header.byte_order != ORDER) die ("incorrect byte order in heap image\n"); if (image_header.magic != IMAGE_MAGIC) die ("bad magic number (%#x) in heap image\n", image_header.magic); if ((image_header.kind != EXPORT_HEAP_IMAGE) && (image_header.kind != EXPORT_FN_IMAGE)) die ("bad image kind (%d) in heap image\n", image_header.kind); READ(&inbuf, heap_header); // Check for command-line overrides of heap parameters: // if (params->agegroup0_buffer_bytesize == 0) { params->agegroup0_buffer_bytesize = heap_header.agegroup0_buffer_bytesize; } if (params->active_agegroups < heap_header.active_agegroups) { params->active_agegroups = heap_header.active_agegroups; } if (params->oldest_agegroup_retaining_fromspace_sibs_between_heapcleanings < 0) { params->oldest_agegroup_retaining_fromspace_sibs_between_heapcleanings = heap_header.oldest_agegroup_retaining_fromspace_sibs_between_heapcleanings; } task = make_task( /*is_boot:*/FALSE, params ); // make_task def in src/c/main/runtime-state.c // Get the run-time pointers into the heap: // *PTR_CAST( Val*, PERVASIVE_PACKAGE_PICKLE_LIST_REFCELL__GLOBAL ) = heap_header.pervasive_package_pickle_list; // This carefully constructed fake looks like a normal // compiled package from the Mythryl side but actually // links to compile C code -- see the hack in // // src/c/main/load-compiledfiles.c // runtime_package__global = heap_header.runtime_pseudopackage; #ifdef ASM_MATH mathvec__global = heap_header.math_package; #endif externs = heapio__read_externs_table (&inbuf); // Read the externals table. READ(&inbuf, image); // Read and initialize the Mythryl state info. // if (image_header.kind == EXPORT_HEAP_IMAGE) { // Load the live registers: // ASSIGN( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL, image.posix_interprocess_signal_handler ); // task->argument = image.stdArg; task->fate = image.stdCont; task->current_closure = image.stdClos; task->program_counter = image.pc; task->exception_fate = image.exception_fate; task->current_thread = image.current_thread; // task->callee_saved_registers[0] = image.calleeSave[0]; task->callee_saved_registers[1] = image.calleeSave[1]; task->callee_saved_registers[2] = image.calleeSave[2]; read_heap (&inbuf, &heap_header, task, externs); // Read the Mythryl heap. /* heapcleaner_messages_are_enabled__global = TRUE; */ // Heapcleaning messages are on by default for interactive images. } else { // EXPORT_FN_IMAGE // Restore the signal handler: // ASSIGN( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL, image.posix_interprocess_signal_handler ); // Read the Mythryl heap: // task->argument = image.stdArg; read_heap (&inbuf, &heap_header, task, externs); // Initialize the calling context (taken from run_mythryl_function__may_heapclean): // run_mythryl_function__may_heapclean def in src/c/main/run-mythryl-code-and-runtime-eventloop.c // Val function_to_run = task->argument; // task->exception_fate = PTR_CAST( Val, handle_uncaught_exception_closure_v + 1 ); task->current_thread = HEAP_VOID; // task->fate = PTR_CAST( Val, return_to_c_level_c ); task->current_closure = function_to_run; // task->program_counter = task->link_register = GET_CODE_ADDRESS_FROM_CLOSURE( function_to_run ); // Last use of 'function_to_run'. // Set up the arguments to the imported function: // Val program_name = make_ascii_string_from_c_string__may_heapclean(task, mythryl_program_name__global, extra_roots); Roots roots1 = { &program_name, extra_roots }; // Val args = make_ascii_strings_from_vector_of_c_strings__may_heapclean (task, commandline_args_without_argv0_or_runtime_args__global, &roots1 ); task->argument = make_two_slot_record( task, program_name, args ); // debug_say("arg = %#x : [%#x, %#x]\n", task->argument, GET_TUPLE_SLOT_AS_VAL(task->argument, 0), GET_TUPLE_SLOT_AS_VAL(task->argument, 1)); // Heapcleaner messages are off by // default for spawn_to_disk images: // heapcleaner_messages_are_enabled__global = FALSE; } FREE( externs ); if (inbuf.file) fclose (inbuf.file); if (verbosity__global > 0) say(" done\n"); return task; } // fun import_heap_image__may_heapclean