FAR void *group_malloc(FAR struct task_group_s *group, size_t nbytes) { /* A NULL group pointer means the current group */ if (!group) { FAR struct tcb_s *tcb = this_task(); DEBUGASSERT(tcb && tcb->group); group = tcb->group; } /* Check the group type */ if ((group->tg_flags & GROUP_FLAG_PRIVILEGED) != 0) { /* It is a privileged group... use the kernel mode memory allocator */ return kmm_malloc(nbytes); } else { /* This is an unprivileged group... use the user mode memory * allocator. */ return kumm_malloc(nbytes); } }
int up_create_stack(struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { uint32_t *stack_alloc_ptr; int ret = ERROR; size_t *adj_stack_ptr; /* Move up to next even word boundary if necessary */ size_t adj_stack_size = (stack_size + 3) & ~3; size_t adj_stack_words = adj_stack_size >> 2; /* Allocate the memory for the stack */ #if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size); } else #endif { stack_alloc_ptr = (uint32_t*)kumm_malloc(adj_stack_size); } if (stack_alloc_ptr) { /* This is the address of the last word in the allocation */ adj_stack_ptr = &stack_alloc_ptr[adj_stack_words - 1]; /* Save the values in the TCB */ tcb->adj_stack_size = adj_stack_size; tcb->stack_alloc_ptr = stack_alloc_ptr; tcb->adj_stack_ptr = (void *)((unsigned int)adj_stack_ptr & ~7); ret = OK; } return ret; }
FAR void *rammap(int fd, size_t length, off_t offset) { FAR struct fs_rammap_s *map; FAR uint8_t *alloc; FAR uint8_t *rdbuffer; ssize_t nread; off_t fpos; int errcode; int ret; /* There is a major design flaw that I have not yet thought of fix for: * The goal is to have a single region of memory that represents a single * file and can be shared by many threads. That is, given a filename a * thread should be able to open the file, get a file descriptor, and * call mmap() to get a memory region. Different file descriptors opened * with the same file path should get the same memory region when mapped. * * The design flaw is that I don't have sufficient knowledge to know that * these different file descriptors map to the same file. So, for the time * being, a new memory region is created each time that rammap() is called. * Not very useful! */ /* Allocate a region of memory of the specified size */ alloc = (FAR uint8_t *)kumm_malloc(sizeof(struct fs_rammap_s) + length); if (!alloc) { ferr("ERROR: Region allocation failed, length: %d\n", (int)length); errcode = ENOMEM; goto errout; } /* Initialize the region */ map = (FAR struct fs_rammap_s *)alloc; memset(map, 0, sizeof(struct fs_rammap_s)); map->addr = alloc + sizeof(struct fs_rammap_s); map->length = length; map->offset = offset; /* Seek to the specified file offset */ fpos = lseek(fd, offset, SEEK_SET); if (fpos == (off_t)-1) { /* Seek failed... errno has already been set, but EINVAL is probably * the correct response. */ ferr("ERROR: Seek to position %d failed\n", (int)offset); errcode = EINVAL; goto errout_with_region; } /* Read the file data into the memory region */ rdbuffer = map->addr; while (length > 0) { nread = read(fd, rdbuffer, length); if (nread < 0) { /* Handle the special case where the read was interrupted by a * signal. */ errcode = get_errno(); if (errcode != EINTR) { /* All other read errors are bad. errno is already set. * (but maybe should be forced to EINVAL?). NOTE that if * FS DEBUG is enabled, then the following ferr() macro will * destroy the errno value. */ ferr("ERROR: Read failed: offset=%d errno=%d\n", (int)offset, errcode); #ifdef CONFIG_DEBUG_FS goto errout_with_region; #else goto errout_with_errno; #endif } } /* Check for end of file. */ if (nread == 0) { break; } /* Increment number of bytes read */ rdbuffer += nread; length -= nread; } /* Zero any memory beyond the amount read from the file */ memset(rdbuffer, 0, length); /* Add the buffer to the list of regions */ rammap_initialize(); ret = sem_wait(&g_rammaps.exclsem); if (ret < 0) { goto errout_with_errno; } map->flink = g_rammaps.head; g_rammaps.head = map; sem_post(&g_rammaps.exclsem); return map->addr; errout_with_region: kumm_free(alloc); errout: set_errno(errcode); return MAP_FAILED; errout_with_errno: kumm_free(alloc); return MAP_FAILED; }
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_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size); } else #endif { /* Use the user-space allocator if this is a task or pthread */ tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); } #ifdef CONFIG_DEBUG_FEATURES /* Was the allocation successful? */ if (!tcb->stack_alloc_ptr) { serr("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; /* 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. */ #ifdef CONFIG_STACK_COLORATION memset(tcb->stack_alloc_ptr, 0xaa, stack_size); #endif /* The SH family uses a push-down stack: the stack grows * toward loweraddresses 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 SH stack must be aligned at word (4 byte) * boundaries. If necessary top_of_stack must be rounded * down to the next boundary */ top_of_stack &= ~3; 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; board_autoled_on(LED_STACKCREATED); return OK; } return ERROR; }
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. */ tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); #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. */ #ifdef CONFIG_STACK_COLORATION memset(tcb->stack_alloc_ptr, STACK_COLOR, 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; #if defined(ARCH_HAVE_LEDS) board_autoled_on(LED_STACKCREATED); #endif return OK; } return ERROR; }
int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) { static bool first_task = true; /* 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. */ #ifdef HAVE_KERNEL_HEAP /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size); } else #endif { /* Use the user-space allocator if this is a task or pthread */ tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); } #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. */ #ifdef CONFIG_STACK_COLORATION up_stack_color(tcb->stack_alloc_ptr, tcb->adj_stack_size); #endif if (first_task) { board_led_on(LED_STACKCREATED); first_task = false; } return OK; } return ERROR; }
int elf_loaddtors(FAR struct elf_loadinfo_s *loadinfo) { FAR Elf32_Shdr *shdr; size_t dtorsize; int dtoridx; int ret; int i; DEBUGASSERT(loadinfo->dtors == NULL); /* Allocate an I/O buffer if necessary. This buffer is used by * elf_sectname() to accumulate the variable length symbol name. */ ret = elf_allocbuffer(loadinfo); if (ret < 0) { bdbg("elf_allocbuffer failed: %d\n", ret); return -ENOMEM; } /* Find the index to the section named ".dtors." NOTE: On old ABI system, * .dtors is the name of the section containing the list of destructors; * On newer systems, the similar section is called .fini_array. It is * expected that the linker script will force the section name to be ".dtors" * in either case. */ dtoridx = elf_findsection(loadinfo, ".dtors"); if (dtoridx < 0) { /* This may not be a failure. -ENOENT indicates that the file has no * static destructor section. */ bvdbg("elf_findsection .dtors section failed: %d\n", dtoridx); return ret == -ENOENT ? OK : ret; } /* Now we can get a pointer to the .dtor section in the section header * table. */ shdr = &loadinfo->shdr[dtoridx]; /* Get the size of the .dtor section and the number of destructors that * will need to be called. */ dtorsize = shdr->sh_size; loadinfo->ndtors = dtorsize / sizeof(binfmt_dtor_t); bvdbg("dtoridx=%d dtorsize=%d sizeof(binfmt_dtor_t)=%d ndtors=%d\n", dtoridx, dtorsize, sizeof(binfmt_dtor_t), loadinfo->ndtors); /* Check if there are any destructors. It is not an error if there * are none. */ if (loadinfo->ndtors > 0) { /* Check an assumption that we made above */ DEBUGASSERT(shdr->sh_size == loadinfo->ndtors * sizeof(binfmt_dtor_t)); /* In the old ABI, the .dtors section is not allocated. In that case, * we need to allocate memory to hold the .dtors and then copy the * from the file into the allocated memory. * * SHF_ALLOC indicates that the section requires memory during * execution. */ if ((shdr->sh_flags & SHF_ALLOC) == 0) { /* Allocate memory to hold a copy of the .dtor section */ loadinfo->ctoralloc = (binfmt_dtor_t*)kumm_malloc(dtorsize); if (!loadinfo->ctoralloc) { bdbg("Failed to allocate memory for .dtors\n"); return -ENOMEM; } loadinfo->dtors = (binfmt_dtor_t *)loadinfo->ctoralloc; /* Read the section header table into memory */ ret = elf_read(loadinfo, (FAR uint8_t*)loadinfo->dtors, dtorsize, shdr->sh_offset); if (ret < 0) { bdbg("Failed to allocate .dtors: %d\n", ret); return ret; } /* Fix up all of the .dtor addresses. Since the addresses * do not lie in allocated memory, there will be no relocation * section for them. */ for (i = 0; i < loadinfo->ndtors; i++) { FAR uintptr_t *ptr = (uintptr_t *)((FAR void *)(&loadinfo->dtors)[i]); bvdbg("dtor %d: %08lx + %08lx = %08lx\n", i, *ptr, (unsigned long)loadinfo->textalloc, (unsigned long)(*ptr + loadinfo->textalloc)); *ptr += loadinfo->textalloc; } } else { /* Save the address of the .dtors (actually, .init_array) where it was * loaded into memory. Since the .dtors lie in allocated memory, they * will be relocated via the normal mechanism. */ loadinfo->dtors = (binfmt_dtor_t*)shdr->sh_addr; } } return OK; }