void DkProcessExit (PAL_NUM exitcode) { ENTER_PAL_CALL(DkProcessExit); _DkProcessExit(exitcode); _DkRaiseFailure(PAL_ERROR_NOTKILLABLE); LEAVE_PAL_CALL(); }
void pal_main (PAL_NUM pal_token, void * pal_addr, const char * pal_name, int argc, const char ** argv, const char ** envp, PAL_HANDLE parent_handle, PAL_HANDLE thread_handle, PAL_HANDLE exec_handle, PAL_HANDLE manifest_handle) { int ret; bool is_parent = !parent_handle; #if PROFILING == 1 __pal_control.host_specific_startup_time = _DkSystemTimeQuery() - pal_state.start_time; #endif pal_state.pal_token = pal_token; pal_state.pal_addr = pal_addr; pal_state.parent_handle = parent_handle; pal_state.pagesize = _DkGetPagesize(); pal_state.alloc_align = _DkGetAllocationAlignment(); pal_state.alloc_shift = pal_state.alloc_align - 1; pal_state.alloc_mask = ~pal_state.alloc_shift; init_slab_mgr(pal_state.alloc_align); char * exec = NULL, * manifest = NULL; if (exec_handle) { exec = __alloca(URI_MAX); ret = _DkStreamGetName(exec_handle, exec, URI_MAX); if (ret < 0) init_fail(-ret, "cannot get executable name"); } if (manifest_handle) { manifest = __alloca(URI_MAX); ret = _DkStreamGetName(manifest_handle, manifest, URI_MAX); if (ret < 0) init_fail(-ret, "cannot get manifest name"); } else { if (is_parent) { #if PROFILING == 1 unsigned long before_find_manifest = _DkSystemTimeQuery(); #endif do { if (exec_handle) { assert(!!exec); /* try open "<exec>.manifest" */ manifest = __alloca(URI_MAX); snprintf(manifest, URI_MAX, "%s.manifest", exec); ret = _DkStreamOpen(&manifest_handle, manifest, PAL_ACCESS_RDONLY, 0, 0, 0); if (!ret) break; } /* try open "file:manifest" */ manifest = "file:manifest"; ret = _DkStreamOpen(&manifest_handle, manifest, PAL_ACCESS_RDONLY, 0, 0, 0); if (!ret) break; /* well, there is no manifest file, leave it alone */ if (!manifest_handle) printf("Can't fine any manifest, will run without one\n"); } while (0); #if PROFILING == 1 pal_state.manifest_loading_time += _DkSystemTimeQuery() - before_find_manifest; #endif } } /* load manifest if there is one */ if (manifest_handle) { #if PROFILING == 1 unsigned long before_load_manifest = _DkSystemTimeQuery(); #endif PAL_STREAM_ATTR attr; ret = _DkStreamAttributesQuerybyHandle(manifest_handle, &attr); if (ret < 0) init_fail(-ret, "cannot open manifest file"); void * cfg_addr = NULL; int cfg_size = attr.pending_size; ret = _DkStreamMap(manifest_handle, &cfg_addr, PAL_PROT_READ, 0, ALLOC_ALIGNUP(cfg_size)); if (ret < 0) init_fail(-ret, "cannot open manifest file"); struct config_store * root_config = malloc(sizeof(struct config_store)); root_config->raw_data = cfg_addr; root_config->raw_size = cfg_size; root_config->malloc = malloc; root_config->free = free; const char * errstring = NULL; if ((ret = read_config(root_config, loader_filter, &errstring)) < 0) init_fail(-ret, errstring); pal_state.root_config = root_config; #if PROFILING == 1 pal_state.manifest_loading_time += _DkSystemTimeQuery() - before_load_manifest; #endif } /* if there is no executable, try to find one in the manifest */ if (is_parent && !exec_handle) { exec = __alloca(URI_MAX); assert(!!pal_state.root_config); ret = get_config(pal_state.root_config, "loader.exec", exec, URI_MAX); if (ret > 0) { ret = _DkStreamOpen(&exec_handle, exec, PAL_ACCESS_RDONLY, 0, 0, 0); if (ret < 0) init_fail(-ret, "cannot open executable"); /* must be a ELF */ if (check_elf_object(exec_handle) < 0) init_fail(PAL_ERROR_INVAL, "executable is not a ELF binary"); } else { exec = NULL; } } if (is_parent && !exec_handle && !manifest_handle) { printf("USAGE: %s [executable|manifest] args ...\n", pal_name); _DkProcessExit(0); return; } pal_state.manifest = manifest; pal_state.manifest_handle = manifest_handle; pal_state.exec = exec; pal_state.exec_handle = exec_handle; const char * first_argv = *argv; argc--; argv++; if (is_parent && exec_handle) { first_argv = exec; if (pal_state.root_config) { char cfgbuf[CONFIG_MAX]; ret = get_config(pal_state.root_config, "loader.execname", cfgbuf, CONFIG_MAX); if (ret > 0) first_argv = remalloc(cfgbuf, ret + 1); } } if (pal_state.root_config) load_libraries(); if (exec_handle) { #if PROFILING == 1 unsigned long before_load_exec = _DkSystemTimeQuery(); #endif ret = load_elf_object_by_handle(exec_handle, OBJECT_EXEC); if (ret < 0) init_fail(ret, PAL_STRERROR(ret)); #if PROFILING == 1 pal_state.linking_time += _DkSystemTimeQuery() - before_load_exec; #endif } #if PROFILING == 1 unsigned long before_tail = _DkSystemTimeQuery(); #endif if (pal_state.root_config) { read_envs(&envp); set_debug_type(); set_syscall_symbol(); } __pal_control.process_id = _DkGetProcessId(); __pal_control.host_id = _DkGetHostId(); __pal_control.manifest_handle = manifest_handle; __pal_control.executable = exec; __pal_control.parent_process = parent_handle; __pal_control.first_thread = thread_handle; _DkGetAvailableUserAddressRange(&__pal_control.user_address.start, &__pal_control.user_address.end); __pal_control.pagesize = pal_state.pagesize; __pal_control.alloc_align = pal_state.alloc_align; __pal_control.broadcast_stream = _DkBroadcastStreamOpen(); _DkGetCPUInfo(&__pal_control.cpu_info); __pal_control.mem_info.mem_total = _DkMemoryQuota(); #if PROFILING == 1 pal_state.tail_startup_time += _DkSystemTimeQuery() - before_tail; __pal_control.relocation_time = pal_state.relocation_time; __pal_control.linking_time = pal_state.linking_time; __pal_control.manifest_loading_time = pal_state.manifest_loading_time; __pal_control.allocation_time = pal_state.slab_time; __pal_control.child_creation_time = is_parent ? 0 : pal_state.start_time - pal_state.process_create_time; #endif /* Now we will start the execution */ start_execution(first_argv, argc, argv, envp); /* We wish we will never reached here */ init_fail(PAL_ERROR_DENIED, "unexpected termination"); }