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_NUTTX_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 *)kmalloc(stack_size); } else #endif { stack_alloc_ptr = (uint32_t*)kumalloc(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; }
int apb_alloc(FAR struct audio_buf_desc_s * bufdesc) { uint32_t bufsize; int ret; struct ap_buffer_s *pBuf; DEBUGASSERT(bufdesc->u.ppBuffer != NULL); /* Perform a user mode allocation */ bufsize = sizeof(struct ap_buffer_s) + bufdesc->numbytes; pBuf = kumalloc(bufsize); *bufdesc->u.ppBuffer = pBuf; /* Test if the allocation was successful or not */ if (*bufdesc->u.ppBuffer == NULL) ret = -ENOMEM; else { /* Populate the buffer contents */ memset(pBuf, bufsize, 0); pBuf->i.channels = 1; pBuf->crefs = 1; pBuf->nmaxbytes = bufdesc->numbytes; pBuf->nbytes = 0; #ifdef CONFIG_AUDIO_MULTI_SESSION pBuf->session = bufdesc->session; #endif sem_init(&pBuf->sem, 0, 1); ret = sizeof(struct audio_buf_desc_s); } return ret; }
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 struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb) { FAR struct streamlist *slist; FAR FILE *stream; int err = OK; int ret; int i; /* Check input parameters */ if (fd < 0) { err = EBADF; goto errout; } /* A NULL TCB pointer means to use this threads TCB. This is a little * hack the let's this function be called from user-space (via a syscall) * without having access to the TCB. */ if (!tcb) { tcb = sched_self(); } DEBUGASSERT(tcb && tcb->group); /* Verify that this is a valid file/socket descriptor and that the * requested access can be support. * * Is this fd in the range of valid file descriptors? Socket descriptors * lie in a different range. */ #if CONFIG_NFILE_DESCRIPTORS > 0 if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) #endif { /* No.. If networking is enabled then this might be a socket * descriptor. */ #if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 ret = net_checksd(fd, oflags); #else /* No networking... it is just a bad descriptor */ err = EBADF; goto errout; #endif } /* The descriptor is in a valid range to file descriptor... perform some more checks */ #if CONFIG_NFILE_DESCRIPTORS > 0 else { ret = fs_checkfd(tcb, fd, oflags); } #endif /* Do we have a good descriptor of some sort? */ if (ret < 0) { /* No... return the reported error */ err = -ret; goto errout; } /* Get the stream list from the TCB */ #if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) slist = tcb->group->tg_streamlist; #else slist = &tcb->group->tg_streamlist; #endif /* Find an unallocated FILE structure in the stream list */ ret = sem_wait(&slist->sl_sem); if (ret != OK) { goto errout_with_errno; } for (i = 0 ; i < CONFIG_NFILE_STREAMS; i++) { stream = &slist->sl_streams[i]; if (stream->fs_fd < 0) { /* Zero the structure */ #if CONFIG_STDIO_BUFFER_SIZE > 0 memset(stream, 0, sizeof(FILE)); #elif CONFIG_NUNGET_CHARS > 0 stream->fs_nungotten = 0; #endif #if CONFIG_STDIO_BUFFER_SIZE > 0 /* Initialize the semaphore the manages access to the buffer */ (void)sem_init(&stream->fs_sem, 0, 1); /* Allocate the IO buffer */ stream->fs_bufstart = kumalloc(CONFIG_STDIO_BUFFER_SIZE); if (!stream->fs_bufstart) { err = ENOMEM; goto errout_with_sem; } /* Set up pointers */ stream->fs_bufend = &stream->fs_bufstart[CONFIG_STDIO_BUFFER_SIZE]; stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufpos = stream->fs_bufstart; stream->fs_bufread = stream->fs_bufstart; #endif /* Save the file description and open flags. Setting the * file descriptor locks this stream. */ stream->fs_fd = fd; stream->fs_oflags = (uint16_t)oflags; sem_post(&slist->sl_sem); return stream; } } /* No free stream available.. report ENFILE */ err = ENFILE; #if CONFIG_STDIO_BUFFER_SIZE > 0 errout_with_sem: #endif sem_post(&slist->sl_sem); errout: set_errno(err); errout_with_errno: 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 setenv(FAR const char *name, FAR const char *value, int overwrite) { FAR struct tcb_s *rtcb; FAR struct task_group_s *group; FAR char *pvar; FAR char *newenvp; int newsize; int varlen; int ret = OK; /* Verify input parameter */ if (!name) { ret = EINVAL; goto errout; } /* if no value is provided, then this is the same as unsetenv (unless * overwrite is false) */ if (!value || *value == '\0') { /* If overwite is set then this is the same as unsetenv */ if (overwrite) { return unsetenv(name); } else { /* Otherwise, it is a request to remove a variable without altering it? */ return OK; } } /* Get a reference to the thread-private environ in the TCB. */ sched_lock(); rtcb = (FAR struct tcb_s*)g_readytorun.head; group = rtcb->group; DEBUGASSERT(group); /* Check if the variable already exists */ if (group->tg_envp && (pvar = env_findvar(group, name)) != NULL) { /* It does! Do we have permission to overwrite the existing value? */ if (!overwrite) { /* No.. then just return success */ sched_unlock(); return OK; } /* Yes.. just remove the name=value pair from the environment. It will * be added again below. Note that we are responsible for reallocating * the environment buffer; this will happen below. */ (void)env_removevar(group, pvar); } /* Get the size of the new name=value string. The +2 is for the '=' and for * null terminator */ varlen = strlen(name) + strlen(value) + 2; /* Then allocate or reallocate the environment buffer */ if (group->tg_envp) { newsize = group->tg_envsize + varlen; newenvp = (FAR char *)kurealloc(group->tg_envp, newsize); if (!newenvp) { ret = ENOMEM; goto errout_with_lock; } pvar = &newenvp[group->tg_envsize]; } else { newsize = varlen; newenvp = (FAR char *)kumalloc(varlen); if (!newenvp) { ret = ENOMEM; goto errout_with_lock; } pvar = newenvp; } /* Save the new buffer and size */ group->tg_envp = newenvp; group->tg_envsize = newsize; /* Now, put the new name=value string into the environment buffer */ sprintf(pvar, "%s=%s", name, value); sched_unlock(); return OK; errout_with_lock: sched_unlock(); errout: errno = ret; return ERROR; }