TCB_ID taskTcb( int taskId ) { TCB_ID tcbId; /* If 0, return current task id */ if (taskId == 0) { tcbId = taskIdCurrent; } else { /* Convert to pointer to TCB struct */ tcbId = (TCB_ID) taskId; /* Verify that it is actually a task */ if (TASK_ID_VERIFY(tcbId) != OK) { /* errno set by TASK_ID_VERIFY() */ tcbId = NULL; } } return tcbId; }
STATUS taskResume( int taskId ) { STATUS status; TCB_ID tcbId; /* If try to resume current task */ if (taskId == 0) { status = OK; } else { tcbId = (TCB_ID) taskId; /* Verify that it is actually a task */ if (TASK_ID_VERIFY(tcbId) != OK) { /* errno set by TASK_ID_VERIFY() */ status = ERROR; } else { /* Put on queue if in kernel mode */ if (kernelState == TRUE) { /* Put on kernel queue */ workQAdd1((FUNCPTR) vmxResume, (ARG) tcbId); status = OK; } else { /* Enter kernel mode */ kernelState = TRUE; /* Resume task */ vmxResume(tcbId); /* Exit kernel mode */ vmxExit(); status = OK; } } } return status; }
static void command_get_context(char * token, Channel * c) { int err = 0; char id[256]; pid_t pid, parent; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); pid = id2pid(id, &parent); write_stringz(&c->out, "R"); write_stringz(&c->out, token); pid = id2pid(id, &parent); if (pid != 0 && parent == 0) { #if defined(WIN32) #elif defined(_WRS_KERNEL) if (TASK_ID_VERIFY(pid) == ERROR) err = ERR_INV_CONTEXT; #elif defined(__APPLE__) #else struct stat st; char dir[FILE_PATH_SIZE]; snprintf(dir, sizeof(dir), "/proc/%d", pid); if (lstat(dir, &st) < 0) err = errno; else if (!S_ISDIR(st.st_mode)) err = ERR_INV_CONTEXT; #endif } write_errno(&c->out, err); if (err == 0 && pid != 0 && parent == 0) { write_context(&c->out, pid); write_stream(&c->out, 0); } else { write_stringz(&c->out, "null"); } write_stream(&c->out, MARKER_EOM); }
STATUS taskDestroy( int taskId, BOOL freeStack, unsigned timeout, BOOL forceDestroy ) { STATUS status; int i, level; TCB_ID tcbId; if (INT_RESTRICT() != OK) { errnoSet (S_intLib_NOT_ISR_CALLABLE); return ERROR; } /* Get task context */ tcbId = taskTcb(taskId); if (tcbId == NULL) return ERROR; /* If task self destruct and excption lib installed */ if (tcbId == taskIdCurrent) { /* Wait for safe to destroy */ while (tcbId->safeCount > 0) taskUnsafe(); /* Kill it */ status = excJobAdd( (VOIDFUNCPTR) taskDestroy, (ARG) tcbId, (ARG) freeStack, (ARG) WAIT_NONE, (ARG) FALSE, (ARG) 0, (ARG) 0 ); /* Block here and suspend */ while(status == OK) taskSuspend(0); } /* End if task self destruct and exception lib installed */ taskDestroyLoop: /* Lock interrupts */ INT_LOCK(level); /* Check id */ if (TASK_ID_VERIFY(tcbId) != OK) { /* errno set by taskIdVerify() */ /* Unlock interrupts */ INT_UNLOCK(level); return ERROR; } /* Mask all signals */ if (tcbId->pSignalInfo != NULL) tcbId->pSignalInfo->sigt_blocked = 0xffffffff; /* Block here for safe and running locked tasks */ while ( (tcbId->safeCount > 0) || ( (tcbId->status == TASK_READY) && (tcbId->lockCount > 0) ) ) { /* Enter kernel mode */ kernelState = TRUE; /* Unlock interrupts */ INT_UNLOCK(level); /* Check if force deletion, or suicide */ if (forceDestroy || (tcbId == taskIdCurrent)) { /* Remove protections */ tcbId->safeCount = 0; tcbId->lockCount = 0; /* Check if flush of safety queue is needed */ if (Q_FIRST(&tcbId->safetyQ) != NULL) vmxPendQFlush(&tcbId->safetyQ); /* Exit trough kernel */ vmxExit(); } else { /* Not forced deletion or suicide */ /* Put task on safe queue */ if (vmxPendQPut(&tcbId->safetyQ, timeout) != OK) { /* Exit trough kernel */ vmxExit(); errnoSet (S_taskLib_INVALID_TIMEOUT); return ERROR; } /* Exit trough kernel */ status = vmxExit(); /* Check for restart */ if (status == SIG_RESTART) { timeout = (sigTimeoutRecalc)(timeout); goto taskDestroyLoop; } /* Check if unsuccessful */ if (status == ERROR) { /* timer should have set errno to S_objLib_TIMEOUT */ return ERROR; } } /* End else forced or suicide */ /* Lock interrupts */ INT_LOCK(level); /* Now verify class id again */ if (TASK_ID_VERIFY(tcbId) != OK) { /* errno set by taskIdVerify() */ /* Unlock interrupts */ INT_UNLOCK(level); return ERROR; } } /* End while blocked by safety */ /* Now only one cadidate is selected for deletion */ /* Make myself safe */ taskSafe(); /* Protet deletion cadidate */ tcbId->safeCount++; /* Check if not suicide */ if (tcbId != taskIdCurrent) { /* Enter kernel mode */ kernelState = TRUE; /* Unlock interrupts */ INT_UNLOCK(level); /* Suspend victim */ vmxSuspend(tcbId); /* Exit trough kernel */ vmxExit(); } else { /* Unlock interrupts */ INT_UNLOCK(level); } /* Run deletion hooks */ for (i = 0; i < MAX_TASK_DELETE_HOOKS; i++) if (taskDeleteHooks[i] != NULL) (*taskDeleteHooks[i])(tcbId); /* Lock task */ taskLock(); /* If dealloc and options dealloc stack */ if ( freeStack && (tcbId->options & TASK_OPTIONS_DEALLOC_STACK) ) { #if (_STACK_DIR == _STACK_GROWS_DOWN) objFree(taskClassId, tcbId->pStackEnd); #else /* _STACK_GROWS_UP */ objFree(taskClassId, tbcId - TASK_EXTRA_BYTES); #endif /* _STACK_DIR */ } /* Lock interrupts */ INT_LOCK(level); /* Invalidate id */ objCoreTerminate(&tcbId->objCore); /* Enter kernel mode */ kernelState = TRUE; /* Unlock interrupts */ INT_UNLOCK(level); /* Delete task */ status = vmxDelete(tcbId); /* Check if safe quque needs to be flushed */ if (Q_FIRST(&tcbId->safetyQ) != NULL) vmxPendQFlush(&tcbId->safetyQ); /* Exit trough kernel */ vmxExit(); /* Unprotect */ taskUnlock(); taskUnsafe(); return OK; }