STATUS taskRestart( int taskId ) { TCB_ID tcbId; char *name, *rename; int len; unsigned priority; int options; char *pStackBase; unsigned stackSize; FUNCPTR entry; ARG args[MAX_TASK_ARGS]; STATUS status; if (INT_RESTRICT() != OK) { errnoSet(S_intLib_NOT_ISR_CALLABLE); return ERROR; } /* If self restart */ if ( (taskId == 0) || (taskId == (int) taskIdCurrent) ) { /* Task must be unsafe */ while (taskIdCurrent->safeCount > 0) taskSafe(); /* Spawn a task that will restart this task */ taskSpawn(restartTaskName, restartTaskPriority, restartTaskOptions, restartTaskStackSize, taskRestart, (ARG) taskIdCurrent, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0, (ARG) 0); /* Wait for restart */ while (1) taskSuspend(0); } /* End if self restart */ /* Get task context */ tcbId = taskTcb(taskId); if (tcbId == NULL) return ERROR; /* TASK_ID_VERIFY() already done by taskTcb() */ /* Copy task data */ priority = tcbId->priority; options = tcbId->options; entry = tcbId->entry; pStackBase = tcbId->pStackBase; stackSize = (tcbId->pStackEnd - tcbId->pStackBase) * _STACK_DIR; taskArgGet(tcbId, pStackBase, args); /* Copy name if needed */ name = tcbId->name; rename = NULL; if (name != NULL) { len = strlen(name) + 1; rename = malloc(len); if (rename != NULL) strcpy(rename, name); name = rename; } /* Prevent deletion */ taskSafe(); if (taskTerminate((int) tcbId) != OK) { taskUnsafe(); /* errno set by taskTerminate() */ return ERROR; } /* Initialize task with same data */ status = taskInit(tcbId, name, priority, options, pStackBase, stackSize, entry, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); if (status != OK) { /* errno set by taskInit() */ return ERROR; } /* And start it */ status = taskActivate((int) tcbId); if (status != OK) { /* errno set by taskActivate() */ return ERROR; } /* Make me mortal */ taskUnsafe(); /* Free rename buffer if needed */ if (rename != NULL) free(rename); return OK; }
STATUS msgQSmSend ( SM_MSG_Q_ID smMsgQId, /* message queue on which to send */ char * buffer, /* message to send */ UINT nBytes, /* length of message */ int timeout, /* ticks to wait */ int priority /* MSG_PRI_NORMAL or MSG_PRI_URGENT */ ) { SM_MSG_NODE volatile * pMsg; SM_DL_NODE * prevNode; int level; SM_MSG_Q_ID volatile smMsgQIdv = (SM_MSG_Q_ID volatile) smMsgQId; int temp; /* temp storage */ if (INT_RESTRICT () != OK) /* not ISR callable */ { return (ERROR); } CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = smMsgQIdv->verify; /* PCI bridge bug [SPR 68844]*/ if (SM_OBJ_VERIFY (smMsgQIdv) != OK) { return (ERROR); } if (nBytes > ntohl (smMsgQId->maxMsgLength)) { errno = S_msgQLib_INVALID_MSG_LENGTH; return (ERROR); } TASK_LOCK (); /* windview level 2 event logging, uses the OSE logging routine */ EVT_OBJ_SM_MSGQ (EVENT_MSGQSEND, smMsgQId, buffer, nBytes, timeout, priority,5); /* get a free message by taking free msg Q shared counting semaphore */ if (semSmTake (&smMsgQId->freeQSem, timeout) != OK) { smMsgQId->sendTimeouts = htonl (ntohl (smMsgQId->sendTimeouts) + 1); TASK_UNLOCK (); return (ERROR); } /* a free message was available before timeout, get it */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->freeQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQSend", (char *) &smMsgQId->freeQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } pMsg = (SM_MSG_NODE volatile *) smDllGet (&smMsgQId->freeQ); SM_OBJ_LOCK_GIVE (&smMsgQId->freeQLock, level);/* release lock */ pMsg->msgLength = htonl (nBytes); bcopy (buffer, SM_MSG_NODE_DATA (pMsg), (int) nBytes); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pMsg->msgLength; /* BRIDGE FLUSH [SPR 68334] */ /* now send message */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->msgQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQSend", (char *) &smMsgQId->msgQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } /* insert message in message list according to its priority */ if (priority == MSG_PRI_NORMAL) { prevNode = (SM_DL_NODE *) SM_DL_LAST (&smMsgQId->msgQ); } else prevNode = NULL; smDllInsert (&smMsgQId->msgQ, prevNode, (SM_DL_NODE *) pMsg); SM_OBJ_LOCK_GIVE (&smMsgQId->msgQLock, level);/* release lock */ /* * If another CPU is currently doing a msgQ send * we can have a case where the other CPU has put a message and * is delayed by an interrupt before Giving the shared * semaphore. In that case, this CPU can put its message and Give * the shared semaphore, the receiver will be unblocked by * the Give done by this CPU but the message obtained will * be the one put by the other CPU (FIFO order of messages will be kept). */ /* unblock receiver */ if (semSmGive (&smMsgQId->msgQSem) != OK) { TASK_UNLOCK (); return (ERROR); } TASK_UNLOCK (); return (OK); }
LOCAL STATUS semBTake( SEM_ID semId, unsigned timeout ) { STATUS status; int level; if (INT_RESTRICT() != OK) { errnoSet (S_intLib_NOT_ISR_CALLABLE); status = ERROR; } else { /* Loop here if status is SIG_RESTART */ do { /* Lock interrupts */ INT_LOCK(level); /* Verify class */ if (OBJ_VERIFY(semId, semClassId) != OK) { INT_UNLOCK(level); status = ERROR; break; } /* Check if it is already given back */ if (SEM_OWNER_GET(semId) == NULL) { /* Then take it */ SEM_OWNER_SET(semId, taskIdCurrent); /* Unlock interrupts */ INT_UNLOCK(level); status = OK; break; } if (timeout == WAIT_NONE) { INT_UNLOCK(level); errnoSet(S_objLib_UNAVAILABLE); status = ERROR; break; } /* Enter kernel mode */ kernelState = TRUE; INT_UNLOCK(level); /* Put on pending queue */ vmxPendQPut(&semId->qHead, timeout); /* Exit through kernel */ status = vmxExit(); } while(status == SIG_RESTART); } return status; }
MSG_Q_ID msgQSmCreate ( int maxMsgs, /* max messages that can be queued */ int maxMsgLength, /* max bytes in a message */ int options /* message queue options */ ) { SM_MSG_Q_ID smMsgQId; void * pSmMsgPool; /* pointer to memory for messages */ int nodeSize = SM_MSG_NODE_SIZE (maxMsgLength); int temp; /* temp storage */ if (INT_RESTRICT () != OK) /* restrict ISR from calling */ { return (NULL); } /* * allocate shared memory message queue descriptor from * dedicated shared memory pool. */ smMsgQId = (SM_MSG_Q_ID) smMemPartAlloc ((SM_PART_ID) smMsgQPartId, sizeof (SM_MSG_Q)); if (smMsgQId == NULL) { return (NULL); } /* * allocate shared memory message queue data buffers from * shared memory system pool. */ pSmMsgPool = smMemMalloc (nodeSize * maxMsgs); if (pSmMsgPool == NULL) { smMemPartFree ((SM_PART_ID) smMsgQPartId, (char *) smMsgQId); return (NULL); } /* Initialize shared memory message queue structure */ if (msgQSmInit (smMsgQId, maxMsgs, maxMsgLength, options, pSmMsgPool) !=OK) { smMemPartFree ((SM_PART_ID) smMsgQPartId, (char *) smMsgQId); smMemFree ((char *) pSmMsgPool); return (NULL); } /* update shared infos data */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pSmObjHdr->curNumMsgQ; /* PCI bridge bug [SPR 68844]*/ pSmObjHdr->curNumMsgQ = htonl (ntohl (pSmObjHdr->curNumMsgQ) + 1); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pSmObjHdr->curNumMsgQ; /* BRIDGE FLUSH [SPR 68334] */ return ((MSG_Q_ID) (SM_OBJ_ADRS_TO_ID (smMsgQId))); }