void elf_addrenv_free(FAR struct elf_loadinfo_s *loadinfo) { #ifdef CONFIG_ARCH_ADDRENV int ret; /* Free the address environment */ ret = up_addrenv_destroy(&loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_destroy failed: %d\n", ret); } #else /* If there is an allocation for the ELF image, free it */ if (loadinfo->textalloc != 0) { kumm_free((FAR void *)loadinfo->textalloc); } #endif /* Clear out all indications of the allocated address environment */ loadinfo->textalloc = 0; loadinfo->dataalloc = 0; loadinfo->textsize = 0; loadinfo->datasize = 0; }
void nxflat_addrenv_free(FAR struct nxflat_loadinfo_s *loadinfo) { FAR struct dspace_s *dspace; #ifdef CONFIG_ADDRENV int ret; #endif DEBUGASSERT(loadinfo); dspace = loadinfo->dspace; if (dspace) { #ifdef CONFIG_ADDRENV /* Destroy the address environment */ ret = up_addrenv_destroy(loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_destroy failed: %d\n", ret); } loadinfo->addrenv = 0; #else /* Free the allocated D-Space region */ if (dspace->region) { kufree(dspace->region); } #endif /* Now destroy the D-Space container */ DEBUGASSERT(dspace->crefs == 1); kfree(dspace); loadinfo->dspace = NULL; } }
int up_addrenv_release(FAR struct tcb_s *tcb) { FAR struct z180_cbr_s *cbr; irqstate_t flags; /* Check if the task has an address environment. */ flags = irqsave(); cbr = tcb->xcp.cbr; if (cbr) { /* Nullify the reference to the CBR structure and decrement the number * of references on the CBR. */ tcb->xcp.cbr = NULL; /* If the reference count would decrement to zero, then free the CBR * structure. */ if (cbr->crefs <= 1) { up_addrenv_destroy(cbr); } else { /* Otherwise, just decrement the reference count */ cbr->crefs--; } } irqrestore(flags); return OK; }
int up_addrenv_create(size_t textsize, size_t datasize, size_t heapsize, FAR group_addrenv_t *addrenv) { int ret; binfo("addrenv=%p textsize=%lu datasize=%lu\n", addrenv, (unsigned long)textsize, (unsigned long)datasize); DEBUGASSERT(addrenv); /* Initialize the address environment structure to all zeroes */ memset(addrenv, 0, sizeof(group_addrenv_t)); /* Back the allocation up with physical pages and set up the level 2 mapping * (which of course does nothing until the L2 page table is hooked into * the L1 page table). */ /* Allocate .text space pages */ ret = arm_addrenv_create_region(addrenv->text, ARCH_TEXT_NSECTS, CONFIG_ARCH_TEXT_VBASE, textsize, MMU_L2_UTEXTFLAGS); if (ret < 0) { berr("ERROR: Failed to create .text region: %d\n", ret); goto errout; } /* Allocate .bss/.data space pages. NOTE that a configurable offset is * added to the allocted size. This is matched by the offset that is * used when reporting the virtual data address in up_addrenv_vdata(). */ ret = arm_addrenv_create_region(addrenv->data, ARCH_DATA_NSECTS, CONFIG_ARCH_DATA_VBASE, datasize + ARCH_DATA_RESERVE_SIZE, MMU_L2_UDATAFLAGS); if (ret < 0) { berr("ERROR: Failed to create .bss/.data region: %d\n", ret); goto errout; } #ifdef CONFIG_BUILD_KERNEL /* Initialize the shared data are at the beginning of the .bss/.data * region. */ ret = up_addrenv_initdata((uintptr_t)addrenv->data[0] & PMD_PTE_PADDR_MASK); if (ret < 0) { berr("ERROR: Failed to initialize .bss/.data region: %d\n", ret); goto errout; } #endif #ifdef CONFIG_BUILD_KERNEL /* Allocate heap space pages */ ret = arm_addrenv_create_region(addrenv->heap, ARCH_HEAP_NSECTS, CONFIG_ARCH_HEAP_VBASE, heapsize, MMU_L2_UDATAFLAGS); if (ret < 0) { berr("ERROR: Failed to create heap region: %d\n", ret); goto errout; } /* Save the initial heap size allocated. This will be needed when * the heap data structures are initialized. */ addrenv->heapsize = (size_t)ret << MM_PGSHIFT; #endif return OK; errout: up_addrenv_destroy(addrenv); return ret; }
int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize) { FAR struct dspace_s *dspace; #ifdef CONFIG_ADDRENV FAR void *vaddr; hw_addrenv_t oldenv; int ret; #endif DEBUGASSERT(!loadinfo->dspace); /* Allocate the struct dspace_s container for the D-Space allocation */ dspace = (FAR struct dspace_s *)kmalloc(sizeof(struct dspace_s)); if (dspace == 0) { bdbg("ERROR: Failed to allocate DSpace\n"); return -ENOMEM; } #ifdef CONFIG_ADDRENV /* Create a D-Space address environment for the new NXFLAT task */ ret = up_addrenv_create(envsize, &loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_create failed: %d\n", ret); goto errout_with_dspace; } /* Get the virtual address associated with the start of the address * environment. This is the base address that we will need to use to * access the D-Space region (but only if the address environment has been * selected. */ ret = up_addrenv_vaddr(loadinfo->addrenv, &vaddr); if (ret < 0) { bdbg("ERROR: up_addrenv_vaddr failed: %d\n", ret); goto errout_with_addrenv; } /* Clear all of the allocated D-Space memory. We have to temporarily * selected the D-Space address environment to do this. */ ret = up_addrenv_select(loadinfo->addrenv, &oldenv); if (ret < 0) { bdbg("ERROR: up_addrenv_select failed: %d\n", ret); goto errout_with_addrenv; } memset(vaddr, 0, envsize); ret = up_addrenv_restore(oldenv); if (ret < 0) { bdbg("ERROR: up_addrenv_restore failed: %d\n", ret); goto errout_with_addrenv; } /* Success... save the fruits of our labor */ loadinfo->dspace = dspace; dspace->crefs = 1; dspace->region = (FAR uint8_t *)vaddr; return OK; errout_with_addrenv: (void)up_addrenv_destroy(loadinfo->addrenv); loadinfo->addrenv = 0; errout_with_dspace: kfree(dspace); return ret; #else /* Allocate (and zero) memory to hold the ELF image */ dspace->region = (FAR uint8_t *)kuzalloc(envsize); if (!dspace->region) { kfree(dspace); return -ENOMEM; } loadinfo->dspace = dspace; dspace->crefs = 1; return OK; #endif }
static inline void group_release(FAR struct task_group_s *group) { /* Free all un-reaped child exit status */ #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) group_removechildren(group); #endif #ifndef CONFIG_DISABLE_SIGNALS /* Release pending signals */ sig_release(group); #endif #ifndef CONFIG_DISABLE_PTHREAD /* Release pthread resources */ pthread_release(group); #endif #if CONFIG_NFILE_DESCRIPTORS > 0 /* Free all file-related resources now. We really need to close files as * soon as possible while we still have a functioning task. */ /* Free resources held by the file descriptor list */ files_releaselist(&group->tg_filelist); #if CONFIG_NFILE_STREAMS > 0 /* Free resource held by the stream list */ lib_stream_release(group); #endif /* CONFIG_NFILE_STREAMS */ #endif /* CONFIG_NFILE_DESCRIPTORS */ #if CONFIG_NSOCKET_DESCRIPTORS > 0 /* Free resource held by the socket list */ net_releaselist(&group->tg_socketlist); #endif /* CONFIG_NSOCKET_DESCRIPTORS */ #ifndef CONFIG_DISABLE_ENVIRON /* Release all shared environment variables */ env_release(group); #endif #ifndef CONFIG_DISABLE_MQUEUE /* Close message queues opened by members of the group */ mq_release(group); #endif #if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_SHM) /* Release any resource held by shared memory virtual page allocator */ (void)shm_group_release(group); #endif #ifdef CONFIG_ARCH_ADDRENV /* Destroy the group address environment */ (void)up_addrenv_destroy(&group->tg_addrenv); /* Mark no address environment */ g_gid_current = 0; #endif #if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) /* Remove the group from the list of groups */ group_remove(group); #endif #ifdef HAVE_GROUP_MEMBERS /* Release the members array */ if (group->tg_members) { sched_kfree(group->tg_members); group->tg_members = NULL; } #endif #if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_MM_KERNEL_HEAP) /* In a flat, single-heap build. The stream list is part of the * group structure and, hence will be freed when the group structure * is freed. Otherwise, it is separately allocated an must be * freed here. */ # if defined(CONFIG_BUILD_PROTECTED) /* In the protected build, the task's stream list is always allocated * and freed from the single, global user allocator. */ sched_ufree(group->tg_streamlist); # elif defined(CONFIG_BUILD_KERNEL) /* In the kernel build, the unprivileged process' stream list will be * allocated from with its per-process, private user heap. But in that * case, there is no reason to do anything here: That allocation resides * in the user heap which which be completely freed when we destroy the * process' address environment. */ if ((group->tg_flags & GROUP_FLAG_PRIVILEGED) != 0) { /* But kernel threads are different in this build configuration: Their * stream lists were allocated from the common, global kernel heap and * must explicitly freed here. */ sched_kfree(group->tg_streamlist); } # endif #endif #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) /* If there are threads waiting for this group to be freed, then we cannot * yet free the memory resources. Instead just mark the group deleted * and wait for those threads complete their waits. */ if (group->tg_nwaiters > 0) { group->tg_flags |= GROUP_FLAG_DELETED; } else #endif { /* Release the group container itself */ sched_kfree(group); } }
int nxflat_addrenv_alloc(FAR struct nxflat_loadinfo_s *loadinfo, size_t envsize) { FAR struct dspace_s *dspace; #ifdef CONFIG_ARCH_ADDRENV FAR void *vdata; save_addrenv_t oldenv; size_t heapsize; int ret; #endif DEBUGASSERT(!loadinfo->dspace); /* Allocate the struct dspace_s container for the D-Space allocation */ dspace = (FAR struct dspace_s *)kmm_malloc(sizeof(struct dspace_s)); if (dspace == 0) { bdbg("ERROR: Failed to allocate DSpace\n"); return -ENOMEM; } #ifdef CONFIG_ARCH_ADDRENV /* Determine the heapsize to allocate. If there is no dynamic stack then * heapsize must at least as big as the fixed stack size since the stack * will be allocated from the heap in that case. */ #ifdef CONFIG_ARCH_STACK_DYNAMIC heapsize = ARCH_HEAP_SIZE; #else heapsize = MIN(loadinfo->stacksize, ARCH_HEAP_SIZE); #endif /* Create a D-Space address environment for the new NXFLAT task */ ret = up_addrenv_create(0, envsize, heapsize, &loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_create failed: %d\n", ret); goto errout_with_dspace; } /* Get the virtual address associated with the start of the address * environment. This is the base address that we will need to use to * access the D-Space region (but only if the address environment has been * selected. */ ret = up_addrenv_vdata(&loadinfo->addrenv, 0, &vdata); if (ret < 0) { bdbg("ERROR: up_addrenv_vdata failed: %d\n", ret); goto errout_with_addrenv; } /* Clear all of the allocated D-Space memory. We have to temporarily * selected the D-Space address environment to do this. */ ret = up_addrenv_select(loadinfo->addrenv, &oldenv); if (ret < 0) { bdbg("ERROR: up_addrenv_select failed: %d\n", ret); goto errout_with_addrenv; } memset(vdata, 0, envsize); ret = up_addrenv_restore(oldenv); if (ret < 0) { bdbg("ERROR: up_addrenv_restore failed: %d\n", ret); goto errout_with_addrenv; } /* Success... save the fruits of our labor */ loadinfo->dspace = dspace; dspace->crefs = 1; dspace->region = (FAR uint8_t *)vdata; return OK; errout_with_addrenv: (void)up_addrenv_destroy(&loadinfo->addrenv); loadinfo->addrenv = 0; errout_with_dspace: kmm_free(dspace); return ret; #else /* Allocate (and zero) memory to hold the ELF image */ dspace->region = (FAR uint8_t *)kumm_zalloc(envsize); if (!dspace->region) { kmm_free(dspace); return -ENOMEM; } loadinfo->dspace = dspace; dspace->crefs = 1; return OK; #endif }