int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t textsize, size_t datasize) { #ifdef CONFIG_ARCH_ADDRENV FAR void *vtext; FAR void *vdata; int ret; /* Create an address environment for the new ELF task */ ret = up_addrenv_create(textsize, datasize, &loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_create failed: %d\n", ret); return ret; } /* 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 ELF image (but only if the address environment has been * selected. */ ret = up_addrenv_vtext(&loadinfo->addrenv, &vtext); if (ret < 0) { bdbg("ERROR: up_addrenv_vtext failed: %d\n", ret); return ret; } ret = up_addrenv_vdata(&loadinfo->addrenv, textsize, &vdata); if (ret < 0) { bdbg("ERROR: up_adup_addrenv_vdatadrenv_vtext failed: %d\n", ret); return ret; } loadinfo->textalloc = (uintptr_t)vtext; loadinfo->dataalloc = (uintptr_t)vdata; return OK; #else /* Allocate memory to hold the ELF image */ loadinfo->textalloc = (uintptr_t)kuzalloc(textsize + datasize); if (!loadinfo->textalloc) { return -ENOMEM; } loadinfo->dataalloc = loadinfo->textalloc + textsize; return OK; #endif }
int elf_addrenv_alloc(FAR struct elf_loadinfo_s *loadinfo, size_t envsize) { #ifdef CONFIG_ADDRENV FAR void *vaddr; int ret; /* Create an address environment for the new ELF task */ ret = up_addrenv_create(envsize, &loadinfo->addrenv); if (ret < 0) { bdbg("ERROR: up_addrenv_create failed: %d\n", ret); return ret; } /* 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 ELF image (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); return ret; } loadinfo->elfalloc = (uintptr_t)vaddr; return OK; #else /* Allocate memory to hold the ELF image */ loadinfo->elfalloc = (uintptr_t)kuzalloc(envsize); if (!loadinfo->elfalloc) { return -ENOMEM; } return OK; #endif }
NXHANDLE nx_open(FAR NX_DRIVERTYPE *dev) { FAR struct nxfe_state_s *fe; int ret; /* Sanity checking */ #ifdef CONFIG_DEBUG if (!dev) { errno = EINVAL; return NULL; } #endif /* Allocate the NX state structure. The user-space allocator is used * (if available) for compatibility with the multi-user implementation. */ fe = (FAR struct nxfe_state_s *)kuzalloc(sizeof(struct nxfe_state_s)); if (!fe) { errno = ENOMEM; return NULL; } /* Initialize and configure the server */ ret = nxsu_setup(dev, fe); if (ret < 0) { return NULL; /* nxsu_setup sets errno */ } /* Fill the initial background window */ nxbe_fill(&fe->be.bkgd, &fe->be.bkgd.bounds, fe->be.bgcolor); return (NXHANDLE)fe; }
int group_allocate(FAR struct task_tcb_s *tcb) { FAR struct task_group_s *group; int ret; DEBUGASSERT(tcb && !tcb->cmn.group); /* Allocate the group structure and assign it to the TCB */ group = (FAR struct task_group_s *)kzalloc(sizeof(struct task_group_s)); if (!group) { return -ENOMEM; } #if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_NUTTX_KERNEL) && \ defined(CONFIG_MM_KERNEL_HEAP) /* In a flat, single-heap build. The stream list is allocated with the * group structure. But in a kernel build with a kernel allocator, it * must be separately allocated using a user-space allocator. */ group->tg_streamlist = (FAR struct streamlist *) kuzalloc(sizeof(struct streamlist)); if (!group->tg_streamlist) { kfree(group); return -ENOMEM; } #endif /* Attach the group to the TCB */ tcb->cmn.group = group; #if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) /* Assign the group a unique ID. If g_gidcounter were to wrap before we * finish with task creation, that would be a problem. */ group_assigngid(group); #endif /* Duplicate the parent tasks environment */ ret = env_dup(group); if (ret < 0) { #if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_NUTTX_KERNEL) && \ defined(CONFIG_MM_KERNEL_HEAP) kufree(group->tg_streamlist); #endif kfree(group); tcb->cmn.group = NULL; return ret; } /* Initialize the pthread join semaphore */ #ifndef CONFIG_DISABLE_PTHREAD (void)sem_init(&group->tg_joinsem, 0, 1); #endif return OK; }
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { /* Is there already a stack allocated of a different size? Because of * alignment issues, stack_size might erroneously appear to be of a * different size. Fortunately, this is not a critical operation. */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { /* Yes.. Release the old stack */ up_release_stack(tcb, ttype); } /* Do we need to allocate a new stack? */ if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ #if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif } else #endif { /* Use the user-space allocator if this is a task or pthread */ #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); #else tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); #endif } #ifdef CONFIG_DEBUG /* Was the allocation successful? */ if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); } #endif } /* Did we successfully allocate a stack? */ if (tcb->stack_alloc_ptr) { size_t top_of_stack; /* Yes.. If stack debug is enabled, then fill the stack with a * recognizable value that we can use later to test for high * water marks. */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) memset(tcb->stack_alloc_ptr, 0xaa, stack_size); #endif /* The AVR uses a push-down stack: the stack grows toward lower * addresses in memory. The stack pointer register, points to the * lowest, valid work address (the "top" of the stack). Items on the * stack are referenced as positive word offsets from sp. */ top_of_stack = (size_t)tcb->stack_alloc_ptr + stack_size - 1; /* Save the adjusted stack values in the struct tcb_s */ tcb->adj_stack_ptr = (FAR void *)top_of_stack; tcb->adj_stack_size = stack_size; up_ledon(LED_STACKCREATED); return OK; } return ERROR; }
FAR DIR *opendir(FAR const char *path) { FAR struct inode *inode = NULL; FAR struct fs_dirent_s *dir; FAR const char *relpath; bool isroot = false; int ret; /* If we are given 'nothing' then we will interpret this as * request for the root inode. */ inode_semtake(); if (!path || *path == 0 || strcmp(path, "/") == 0) { inode = root_inode; isroot = true; relpath = NULL; } else { /* We don't know what to do with relative pathes */ if (*path != '/') { ret = -ENOTDIR; goto errout_with_semaphore; } /* Find the node matching the path. */ inode = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL, &relpath); } /* Did we get an inode? */ if (!inode) { /* 'path' is not a does not exist.*/ ret = ENOTDIR; goto errout_with_semaphore; } /* Allocate a type DIR -- which is little more than an inode * container. */ dir = (FAR struct fs_dirent_s *)kuzalloc(sizeof(struct fs_dirent_s)); if (!dir) { /* Insufficient memory to complete the operation.*/ ret = ENOMEM; goto errout_with_semaphore; } /* Populate the DIR structure and return it to the caller. The way that * we do this depends on whenever this is a "normal" pseudo-file-system * inode or a file system mountpoint. */ dir->fd_position = 0; /* This is the position in the read stream */ /* First, handle the special case of the root inode. This must be * special-cased here because the root inode might ALSO be a mountpoint. */ if (isroot) { /* Whatever payload the root inode carries, the root inode is always * a directory inode in the pseudo-file system */ open_pseudodir(inode, dir); } /* Is this a node in the pseudo filesystem? Or a mountpoint? If the node * is the root (isroot == TRUE), then this is a special case. */ #ifndef CONFIG_DISABLE_MOUNTPOINT else if (INODE_IS_MOUNTPT(inode)) { /* Yes, the node is a file system mountpoint */ dir->fd_root = inode; /* Save the inode where we start */ /* Open the directory at the relative path */ ret = open_mountpoint(inode, relpath, dir); if (ret != OK) { goto errout_with_direntry; } } #endif else { /* The node is part of the root pseudo file system. Does the inode * have a child? If so that the child would be the 'root' of a list * of nodes under the directory. */ FAR struct inode *child = inode->i_child; if (child) { /* It looks we have a valid pseudo-filesystem directory node. */ open_pseudodir(child, dir); } else if (!inode->u.i_ops) { /* This is a dangling node with no children and no operations. Set * up to enumerate an empty directory. */ open_emptydir(dir); } else { ret = ENOTDIR; goto errout_with_direntry; } } inode_semgive(); return ((DIR*)dir); /* Nasty goto's make error handling simpler */ errout_with_direntry: kufree(dir); errout_with_semaphore: inode_semgive(); set_errno(ret); return NULL; }
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { /* Is there already a stack allocated of a different size? Because of * alignment issues, stack_size might erroneously appear to be of a * different size. Fortunately, this is not a critical operation. */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { /* Yes.. Release the old stack */ up_release_stack(tcb, ttype); } /* Do we need to allocate a new stack? */ if (!tcb->stack_alloc_ptr) { /* Allocate the stack. If DEBUG is enabled (but not stack debug), * then create a zeroed stack to make stack dumps easier to trace. */ #if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) tcb->stack_alloc_ptr = (uint32_t *)kzalloc(stack_size); #else tcb->stack_alloc_ptr = (uint32_t *)kmalloc(stack_size); #endif } else #endif { /* Use the user-space allocator if this is a task or pthread */ #if defined(CONFIG_DEBUG) && !defined(CONFIG_DEBUG_STACK) tcb->stack_alloc_ptr = (uint32_t *)kuzalloc(stack_size); #else tcb->stack_alloc_ptr = (uint32_t *)kumalloc(stack_size); #endif } #ifdef CONFIG_DEBUG /* Was the allocation successful? */ if (!tcb->stack_alloc_ptr) { sdbg("ERROR: Failed to allocate stack, size %d\n", stack_size); } #endif } /* Did we successfully allocate a stack? */ if (tcb->stack_alloc_ptr) { size_t top_of_stack; size_t size_of_stack; /* The ARM uses a push-down stack: the stack grows toward lower * addresses in memory. The stack pointer register, points to * the lowest, valid work address (the "top" of the stack). Items * on the stack are referenced as positive word offsets from sp. */ top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; /* The ARM stack must be aligned; 4 byte alignment for OABI and * 8-byte alignment for EABI. If necessary top_of_stack must be * rounded down to the next boundary */ top_of_stack = STACK_ALIGN_DOWN(top_of_stack); /* The size of the stack in bytes is then the difference between * the top and the bottom of the stack (+4 because if the top * is the same as the bottom, then the size is one 32-bit element). * The size need not be aligned. */ size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; /* Save the adjusted stack values in the struct tcb_s */ tcb->adj_stack_ptr = (uint32_t*)top_of_stack; tcb->adj_stack_size = size_of_stack; /* If stack debug is enabled, then fill the stack with a * recognizable value that we can use later to test for high * water marks. */ #if defined(CONFIG_DEBUG) && defined(CONFIG_DEBUG_STACK) memset32(tcb->stack_alloc_ptr, 0xdeadbeef, tcb->adj_stack_size/4); #endif up_ledon(LED_STACKCREATED); return OK; } return ERROR; }
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 }