int rt_tbx_delete(TBX *tbx) { CHK_TBX_MAGIC; tbx->magic = 0; if (rt_sem_delete(&(tbx->sndsmx)) || rt_sem_delete(&(tbx->rcvsmx))|| rt_sem_delete(&(tbx->bcbsmx))) { return -EFAULT; } while (tbx->waiting_task) { tbx_signal(tbx); } sched_free(tbx->bufadr); sched_free(tbx->bcbadr); return 0; }
/** * @brief - purge scheduler from system * * @param[in] psched - The pointer to the delete to delete * * @return error code * @retval 0 - scheduler purged * @retval PBSE_OBJBUSY - scheduler deletion not allowed */ int sched_delete(pbs_sched *psched) { pbs_db_obj_info_t obj; pbs_db_sched_info_t dbsched; pbs_db_conn_t *conn = (pbs_db_conn_t *) svr_db_conn; if (psched == NULL) return (0); /* TODO check for scheduler activity and return PBSE_OBJBUSY */ /* delete scheduler from database */ strcpy(dbsched.sched_name, psched->sc_name); obj.pbs_db_obj_type = PBS_DB_SCHED; obj.pbs_db_un.pbs_db_sched = &dbsched; if (pbs_db_delete_obj(conn, &obj) != 0) { snprintf(log_buffer, LOG_BUF_SIZE, "delete of scheduler %s from datastore failed", psched->sc_name); log_err(errno, __func__, log_buffer); } sched_free(psched); return (0); }
void up_release_stack(_TCB *dtcb) { if (dtcb->stack_alloc_ptr) { sched_free(dtcb->stack_alloc_ptr); dtcb->stack_alloc_ptr = NULL; } dtcb->adj_stack_size = 0; }
int up_create_stack(_TCB *tcb, size_t stack_size) { if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { sched_free(tcb->stack_alloc_ptr); tcb->stack_alloc_ptr = NULL; } if (!tcb->stack_alloc_ptr) { #ifdef CONFIG_DEBUG tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size); #else tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size); #endif } if (tcb->stack_alloc_ptr) { size_t top_of_stack; size_t size_of_stack; /* MIPS 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 MIPS 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 _TCB */ tcb->adj_stack_ptr = (uint32_t*)top_of_stack; tcb->adj_stack_size = size_of_stack; up_ledon(LED_STACKCREATED); return OK; } return ERROR; }
void pthread_destroyjoin(FAR join_t *pjoin) { sdbg("pjoin=0x%p\n", pjoin); /* Remove the join info from the set of joins */ (void)pthread_removejoininfo((pid_t)pjoin->thread); /* Destroy its semaphores */ (void)sem_destroy(&pjoin->data_sem); (void)sem_destroy(&pjoin->exit_sem); /* And deallocate the pjoin structure */ sched_free(pjoin); }
void uip_grpfree(FAR struct uip_driver_s *dev, FAR struct igmp_group_s *group) { uip_lock_t flags; grplldbg("Free: %p flags: %02x\n", group, group->flags); /* Cancel the wdog */ flags = uip_lock(); wd_cancel(group->wdog); /* Remove the group structure from the group list in the device structure */ sq_rem((FAR sq_entry_t*)group, &dev->grplist); /* Destroy the wait semapore */ (void)sem_destroy(&group->sem); /* Destroy the wdog */ wd_delete(group->wdog); /* Then release the group structure resources. Check first if this is one * of the pre-allocated group structures that we will retain in a free list. */ #if CONFIG_PREALLOC_IGMPGROUPS > 0 if (IS_PREALLOCATED(group->flags)) { grplldbg("Put back on free list\n"); sq_addlast((FAR sq_entry_t*)group, &g_freelist); uip_unlock(flags); } else #endif { /* No.. deallocate the group structure. Use sched_free() just in case * this function is executing within an interrupt handler. */ uip_unlock(flags); grplldbg("Call sched_free()\n"); sched_free(group); } }
int rt_delete_tasklet(struct rt_tasklet_struct *tasklet) { int pid, thread; rt_remove_tasklet(tasklet); tasklet->handler = 0; pid = ((tasklet->task)->lnxtsk)->pid; copy_to_user(tasklet->usptasklet, tasklet, sizeof(struct rt_tasklet_struct)); rt_task_resume(tasklet->task); while (find_task_by_pid(pid)) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); } thread = tasklet->thread; sched_free(tasklet); return thread; }
int up_use_stack(_TCB *tcb, void *stack, size_t stack_size) { size_t top_of_stack; size_t size_of_stack; if (tcb->stack_alloc_ptr) { sched_free(tcb->stack_alloc_ptr); } /* Save the stack allocation */ tcb->stack_alloc_ptr = 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 _TCB */ tcb->adj_stack_ptr = (uint32_t*)top_of_stack; tcb->adj_stack_size = size_of_stack; return OK; }
void sig_releasependingsigaction(FAR sigq_t *sigq) { irqstate_t saved_state; /* If this is a generally available pre-allocated structyre, * then just put it back in the free list. */ if (sigq->type == SIG_ALLOC_FIXED) { /* Make sure we avoid concurrent access to the free * list from interrupt handlers. */ saved_state = irqsave(); sq_addlast((FAR sq_entry_t*)sigq, &g_sigpendingaction); irqrestore(saved_state); } /* If this is a message pre-allocated for interrupts, * then put it back in the correct free list. */ else if (sigq->type == SIG_ALLOC_IRQ) { /* Make sure we avoid concurrent access to the free * list from interrupt handlers. */ saved_state = irqsave(); sq_addlast((FAR sq_entry_t*)sigq, &g_sigpendingirqaction); irqrestore(saved_state); } /* Otherwise, deallocate it. Note: interrupt handlers * will never deallocate signals because they will not * receive them. */ else if (sigq->type == SIG_ALLOC_DYN) { sched_free(sigq); } }
void env_release(FAR struct task_group_s *group) { DEBUGASSERT(group); /* Free any allocate environment strings */ if (group->tg_envp) { /* Free the environment */ sched_free(group->tg_envp); } /* In any event, make sure that all environment-related varialbles in the * task group structure are reset to initial values. */ group->tg_envsize = 0; group->tg_envp = NULL; }
int sem_close(FAR sem_t *sem) { FAR nsem_t *psem; int ret = ERROR; /* Verify the inputs */ if (sem) { sched_lock(); /* Search the list of named semaphores */ for (psem = (FAR nsem_t*)g_nsems.head; ((psem) && (sem != &psem->sem)); psem = psem->flink); /* Check if we found it */ if (psem) { /* Decrement the count of sem_open connections to this semaphore */ if (psem->nconnect) psem->nconnect--; /* If the semaphore is no long connected to any processes AND the * semaphore was previously unlinked, then deallocate it. */ if (!psem->nconnect && psem->unlinked) { dq_rem((FAR dq_entry_t*)psem, &g_nsems); sched_free(psem); } ret = OK; } sched_unlock(); } return ret; }
void mq_msgqfree(FAR msgq_t *msgq) { FAR mqmsg_t *curr; FAR mqmsg_t *next; /* Deallocate any stranded messages in the message queue. */ curr = (FAR mqmsg_t*)msgq->msglist.head; while (curr) { /* Deallocate the message structure. */ next = curr->next; mq_msgfree(curr); curr = next; } /* Then deallocate the message queue itself */ sched_free(msgq); }
int up_use_stack(_TCB *tcb, void *stack, size_t stack_size) { size_t top_of_stack; size_t size_of_stack; if (tcb->stack_alloc_ptr) { sched_free(tcb->stack_alloc_ptr); } /* Save the stack allocation */ tcb->stack_alloc_ptr = stack; /* The Arm7Tdmi 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 Arm7Tdmi 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 _TCB */ tcb->adj_stack_size = top_of_stack; tcb->adj_stack_size = size_of_stack; return OK; }
int rt_tbx_init(TBX *tbx, int size, int flags) { if (!(tbx->bufadr = sched_malloc(size))) { return -ENOMEM; } if (!(tbx->bcbadr = sched_malloc(size))) { sched_free(tbx->bufadr); return -ENOMEM; } *tbx->bcbadr = TYPE_NONE; memset(tbx->bufadr, 0, size); memset(tbx->bcbadr, 0, size); rt_typed_sem_init(&(tbx->sndsmx), 1, CNT_SEM | flags); rt_typed_sem_init(&(tbx->rcvsmx), 1, CNT_SEM | flags); rt_typed_sem_init(&(tbx->bcbsmx), 1, BIN_SEM | flags); tbx->magic = RT_TBX_MAGIC; tbx->size = tbx->frbs = size; tbx->waiting_task = 0; tbx->waiting_nr = 0; spin_lock_init(&(tbx->buflock)); tbx->fbyte = tbx->avbs = 0; return 0; }
int sched_releasetcb(FAR _TCB *tcb) { int ret = OK; int i; if (tcb) { /* Relase any timers that the task might hold. We do this * before release the PID because it may still be trying to * deliver signals (although interrupts are should be * disabled here). */ #ifndef CONFIG_DISABLE_POSIX_TIMERS #ifdef CONFIG_HAVE_WEAKFUNCTIONS if (timer_deleteall != NULL) #endif { timer_deleteall(tcb->pid); } #endif /* Release the task's process ID if one was assigned. PID * zero is reserved for the IDLE task. The TCB of the IDLE * task is never release so a value of zero simply means that * the process ID was never allocated to this TCB. */ if (tcb->pid) { sched_releasepid(tcb->pid); } /* Delete the thread's stack if one has been allocated */ #ifndef CONFIG_CUSTOM_STACK if (tcb->stack_alloc_ptr) { up_release_stack(tcb); } #endif /* Delete the tasks's allocated DSpace region (external modules only) */ #ifdef CONFIG_PIC if (tcb->dspace) { if (tcb->dspace->crefs <= 1) { sched_free(tcb->dspace); } else { tcb->dspace->crefs--; } } #endif /* Release command line arguments that were allocated for task * start/re-start. */ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_TASK) { for (i = 1; i < CONFIG_MAX_TASK_ARGS+1 && tcb->argv[i]; i++) { sched_free((FAR void*)tcb->argv[i]); } } /* Release any allocated file structures */ ret = sched_releasefiles(tcb); /* Release environment variables */ (void)env_release(tcb); /* And, finally, release the TCB itself */ sched_free(tcb); } return ret; }
int up_create_stack(_TCB *tcb, size_t stack_size) { if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { sched_free(tcb->stack_alloc_ptr); tcb->stack_alloc_ptr = NULL; } if (!tcb->stack_alloc_ptr) { #ifdef CONFIG_DEBUG tcb->stack_alloc_ptr = (uint32_t*)kzalloc(stack_size); #else tcb->stack_alloc_ptr = (uint32_t*)kmalloc(stack_size); #endif } 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 _TCB */ 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 up_create_stack(_TCB *tcb, size_t stack_size) { /* Is there already a stack allocated of a different size? */ if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) { /* Yes.. free it */ sched_free(tcb->stack_alloc_ptr); tcb->stack_alloc_ptr = NULL; } /* Do we need to allocate a 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_DEBUG) && !defined(CONFIG_DEBUG_STACK) tcb->stack_alloc_ptr = (FAR void *)zalloc(stack_size); #else tcb->stack_alloc_ptr = (FAR void *)malloc(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 _TCB */ tcb->adj_stack_ptr = (FAR void *)top_of_stack; tcb->adj_stack_size = stack_size; up_ledon(LED_STACKCREATED); return OK; } return ERROR; }
/* sched_alloc(): allocate and populate a schedule data structure * from a file, specified with a filename string. * * arguments: * @fname: filename of the input schedule to read. * * returns: * pointer to a newly allocated and populated schedule structure, * or NULL on failure. */ sched *sched_alloc (const char *fname) { /* declare required variables: * @sch: pointer to the newly allocated schedule structure. * @buf: character buffer to hold each line of schedule text. * @i1, @i2, @i3: parsed grid indices. * @dscan: number of parsed indices. * @fh: input file handle. */ int dscan, i1, i2, i3; char buf[N_BUF]; sched *sch; FILE *fh; /* allocate a new structure pointer. */ sch = (sched*) malloc(sizeof(sched)); if (!sch) { /* if unsuccessful, output an error message and return. */ failf("failed to allocate schedule pointer"); return NULL; } /* initialize the contents of the structure. */ sch->idx = NULL; sch->w = NULL; sch->n = 0; sch->d = 0; sch->n1 = 0; sch->n2 = 0; sch->n3 = 0; /* check that the input filename is defined. */ if (!fname) { /* if not, output an error message and return. */ failf("schedule filename not supplied"); sched_free(sch); return NULL; } /* open the input file. */ fh = fopen(fname, "r"); if (!fh) { /* if unsuccessful, output an error message and return. */ failf("failed to open schedule file '%s'", fname); sched_free(sch); return NULL; } /* attempt to read the first line of text from the schedule. */ if (!fgets(buf, N_BUF, fh)) { /* if unsuccessful, output an error message and return. */ failf("failed to read from '%s'", fname); sched_free(sch); fclose(fh); return NULL; } /* check for the line format of each dimensionality. */ if (sscanf(buf, FMT_3D, &i1, &i2, &i3) == 3) { /* set three dimensions. */ sch->d = 3; } else if (sscanf(buf, FMT_2D, &i1, &i2) == 2) { /* set two dimensions. */ sch->d = 2; } else if (sscanf(buf, FMT_1D, &i1) == 1) { /* set one dimension. */ sch->d = 1; } /* check for a sane dimensionality. */ if (sch->d == 0) { /* if not sane, output an error message and return. */ failf("failed to determine schedule dimensionality"); sched_free(sch); fclose(fh); return NULL; } /* seek back to the beginning of the schedule file. */ if (fseek(fh, SEEK_SET, 0)) { /* if unsuccessful, output an error message and return. */ failf("failed to seek within the schedule file"); sched_free(sch); fclose(fh); return NULL; } /* loop until the end of the schedule file is reached. */ while (!feof(fh)) { /* read a new line of text from the schedule file. */ if (fgets(buf, N_BUF, fh)) { /* initialize the indices. */ i1 = i2 = i3 = 0; /* parse based on the dimensionality. */ switch (sch->d) { /* one-dimensional. */ case 1: dscan = sscanf(buf, FMT_1D, &i1); break; /* two-dimensional. */ case 2: dscan = sscanf(buf, FMT_2D, &i1, &i2); break; /* three-dimensional. */ case 3: dscan = sscanf(buf, FMT_3D, &i1, &i2, &i3); break; /* else. won't happen. */ default: dscan = 0; break; } /* check for a successful parse. */ if (dscan != sch->d) { /* if not, output an error message and return. */ failf("failed to parse line %d of '%s'", sch->n + 1, fname); sched_free(sch); fclose(fh); return NULL; } /* reallocate the index array. */ sch->n++; sch->idx = (int*) realloc(sch->idx, 3 * sch->n * sizeof(int)); if (!sch->idx) { /* if unsuccessful, output an error message and return. */ failf("failed to reallocate schedule array"); sched_free(sch); fclose(fh); return NULL; } /* store the parsed indices. */ sch->idx[3 * (sch->n - 1) + 0] = i1; sch->idx[3 * (sch->n - 1) + 1] = i2; sch->idx[3 * (sch->n - 1) + 2] = i3; /* update the maximum grid indices. */ if (i1 > sch->n1) sch->n1 = i1; if (i2 > sch->n2) sch->n2 = i2; if (i3 > sch->n3) sch->n3 = i3; } } /* transform the maximum grid indices into sizes. */ if (sch->d >= 1) sch->n1++; if (sch->d >= 2) sch->n2++; if (sch->d >= 3) sch->n3++; /* close the input file handle. */ fclose(fh); /* return the allocated and prepared structure pointer. */ return sch; }
int pthread_create(FAR pthread_t *thread, FAR pthread_attr_t *attr, pthread_startroutine_t start_routine, pthread_addr_t arg) { FAR _TCB *ptcb; FAR join_t *pjoin; int status; int priority; #if CONFIG_RR_INTERVAL > 0 int policy; #endif pid_t pid; /* If attributes were not supplied, use the default attributes */ if (!attr) { attr = &g_default_pthread_attr; } /* Allocate a TCB for the new task. */ ptcb = (FAR _TCB*)kzalloc(sizeof(_TCB)); if (!ptcb) { return ENOMEM; } /* Associate file descriptors with the new task */ status = sched_setuppthreadfiles(ptcb); if (status != OK) { sched_releasetcb(ptcb); return status; } /* Share the parent's envionment */ (void)env_share(ptcb); /* Allocate a detachable structure to support pthread_join logic */ pjoin = (FAR join_t*)kzalloc(sizeof(join_t)); if (!pjoin) { sched_releasetcb(ptcb); return ENOMEM; } /* Allocate the stack for the TCB */ status = up_create_stack(ptcb, attr->stacksize); if (status != OK) { sched_releasetcb(ptcb); sched_free(pjoin); return ENOMEM; } /* Should we use the priority and scheduler specified in the * pthread attributes? Or should we use the current thread's * priority and scheduler? */ if (attr->inheritsched == PTHREAD_INHERIT_SCHED) { /* Get the priority for this thread. */ struct sched_param param; status = sched_getparam(0, ¶m); if (status == OK) { priority = param.sched_priority; } else { priority = SCHED_FIFO; } /* Get the scheduler policy for this thread */ #if CONFIG_RR_INTERVAL > 0 policy = sched_getscheduler(0); if (policy == ERROR) { policy = SCHED_FIFO; } #endif } else { /* Use the priority and scheduler from the attributes */ priority = attr->priority; #if CONFIG_RR_INTERVAL > 0 policy = attr->policy; #endif } /* Mark this task as a pthread (this setting will be needed in * task_schedsetup() when up_initial_state() is called. */ ptcb->flags |= TCB_FLAG_TTYPE_PTHREAD; /* Initialize the task control block */ status = task_schedsetup(ptcb, priority, pthread_start, (main_t)start_routine); if (status != OK) { sched_releasetcb(ptcb); sched_free(pjoin); return EBUSY; } /* Configure the TCB for a pthread receiving on parameter * passed by value */ pthread_argsetup(ptcb, arg); /* Attach the join info to the TCB. */ ptcb->joininfo = (void*)pjoin; /* If round robin scheduling is selected, set the appropriate flag * in the TCB. */ #if CONFIG_RR_INTERVAL > 0 if (policy == SCHED_RR) { ptcb->flags |= TCB_FLAG_ROUND_ROBIN; ptcb->timeslice = CONFIG_RR_INTERVAL / MSEC_PER_TICK; } #endif /* Get the assigned pid before we start the task (who knows what * could happen to ptcb after this!). Copy this ID into the join structure * as well. */ pid = (int)ptcb->pid; pjoin->thread = (pthread_t)pid; /* Initialize the semaphores in the join structure to zero. */ status = sem_init(&pjoin->data_sem, 0, 0); if (status == OK) { status = sem_init(&pjoin->exit_sem, 0, 0); } /* Activate the task */ sched_lock(); if (status == OK) { status = task_activate(ptcb); } if (status == OK) { /* Wait for the task to actually get running and to register * its join_t */ (void)pthread_takesemaphore(&pjoin->data_sem); /* Return the thread information to the caller */ if (thread) *thread = (pthread_t)pid; if (!pjoin->started) status = ERROR; sched_unlock(); (void)sem_destroy(&pjoin->data_sem); } else { sched_unlock(); dq_rem((FAR dq_entry_t*)ptcb, (dq_queue_t*)&g_inactivetasks); (void)sem_destroy(&pjoin->data_sem); (void)sem_destroy(&pjoin->exit_sem); sched_releasetcb(ptcb); sched_free(pjoin); return EIO; } return OK; }