STATUS msgQEvStart ( MSG_Q_ID msgQId, /* msg Q for which to register events */ UINT32 events, /* 32 possible events */ UINT8 options /* event-related msg Q options */ ) { if (events == 0x0) { errnoSet (S_eventLib_ZERO_EVENTS); return (ERROR); } if (INT_RESTRICT () != OK) return (ERROR); /* errno set by INT_RESTRICT() */ TASK_LOCK (); /* to prevent msg Q from being deleted */ if (OBJ_VERIFY(msgQId,msgQClassId) != OK) { TASK_UNLOCK (); return (ERROR); /* errno is set by OBJ_VERIFY */ } /* TASK_UNLOCK() will be done by eventStart() */ return (eventStart ((OBJ_ID)msgQId, &msgQId->events, &msgQEvIsFree, events, options)); }
/* * Convert task ID to a task structure. * Returns locked task. Caller must unlock it after using it. */ struct task * task_lookup(task_t task) { list_t head, n; struct task *t; if (task == TASK_NULL) return NULL; TASK_LOCK(); head = &task_table[TASKHASH(task)]; for (n = list_first(head); n != head; n = list_next(n)) { t = list_entry(n, struct task, link); ASSERT(t->task); if (t->task == task) { TASK_UNLOCK(); mutex_lock(&t->lock); return t; } } TASK_UNLOCK(); /* Not found */ return NULL; }
BOOL memPartBlockIsValid ( PART_ID partId, FAST BLOCK_HDR *pHdr, BOOL isFree /* expected status */ ) { BOOL valid; TASK_LOCK (); /* LOCK PREEMPTION */ semGive (&partId->sem); /* release mutex */ valid = MEM_ALIGNED (pHdr) /* aligned */ && MEM_ALIGNED (2 * pHdr->nWords) /* size is round */ && (pHdr->nWords <= partId->totalWords) /* size <= total */ && (pHdr->free == isFree) /* right alloc-ness */ #if (CPU_FAMILY == SH) && MEM_ALIGNED(NEXT_HDR (pHdr)) /* aligned(08aug95,sa)*/ && MEM_ALIGNED(PREV_HDR (pHdr)) /* aligned(08aug95,sa)*/ #endif && (pHdr == PREV_HDR (NEXT_HDR (pHdr))) /* matches next block */ && (pHdr == NEXT_HDR (PREV_HDR (pHdr))); /* matches prev block */ semTake (&partId->sem, WAIT_FOREVER); /* reacquire mutex */ TASK_UNLOCK (); /* UNLOCK PREEMPTION */ return (valid); }
static STATUS msgQDestroy(MSG_Q_ID msgQId, BOOL dealloc) { Q_JOB_NODE* pNode; FAST int timeout; FAST int nMsgs; /* TODO isr not allowed */ TASK_SAFE(); TASK_LOCK(); if(!IS_CLASS(msgQId, msgQClassId)) { TASK_UNLOCK(); TASK_UNSAFE(); return (ERROR); } objCoreTerminate(&msgQId->objCore); TASK_UNLOCK(); timeout = NO_WAIT; nMsgs = 0; while(nMsgs < msgQId->maxMsgs) { while(((pNode = qJobGet(msgQId, &msgQId->freeQ, timeout)) != NULL) && (pNode != (Q_JOB_NODE*)NONE)) { nMsgs++; } while(((pNode = qJobGet(msgQId, &msgQId->msgQ, timeout)) != NULL) && (pNode != (Q_JOB_NODE*)NONE)) { nMsgs++; } timeout = 1; } kernelState = TRUE; qJobTerminate(&msgQId->msgQ); qJobTerminate(&msgQId->freeQ); kernelExit(); if(dealloc) { objFree(msgQClassId, (char*)msgQId); } TASK_UNSAFE(); return (OK); }
/* * Update task id of the specified task. */ void task_update(struct task *t, task_t task) { TASK_LOCK(); list_remove(&t->link); t->task = task; list_insert(&task_table[TASKHASH(task)], &t->link); TASK_UNLOCK(); }
/* * Free needless task. */ void task_free(struct task *t) { TASK_LOCK(); list_remove(&t->link); mutex_unlock(&t->lock); mutex_destroy(&t->lock); free(t); TASK_UNLOCK(); }
long comSafeDec ( long * pVar ) { long n; TASK_LOCK (); n = --(*pVar); TASK_UNLOCK (); return n; }
long comSafeInc ( long * pVar ) { long n; TASK_LOCK (); n = ++(*pVar); TASK_UNLOCK (); return n; }
int msgQReceive(FAST MSG_Q_ID msgQId, char* buffer, UINT maxNBytes, int timeout) { FAST MSG_NODE* pMsg; FAST int bytesReturned; /* TODO int restrict */ if((int)maxNBytes < 0) { return (ERROR); } TASK_LOCK(); restart: if(!IS_CLASS(msgQId, msgQClassId)) { TASK_UNLOCK(); return (ERROR); } pMsg = (MSG_NODE*)qJobGet(msgQId, &msgQId->msgQ, timeout); if(pMsg == (MSG_NODE*)NONE) { /* timeout recalc */ goto restart; } if(pMsg == NULL) { msgQId->recvTimeouts++; TASK_UNLOCK(); return (ERROR); } bytesReturned = MIN(pMsg->msgLength, maxNBytes); memcpy(buffer, MSG_NODE_DATA(pMsg), bytesReturned); qJobPut(msgQId, &msgQId->freeQ, &pMsg->node, Q_JOB_PRI_DONT_CARE); TASK_UNLOCK(); return (bytesReturned); }
/* * Allocate new task */ int task_alloc(task_t task, struct task **pt) { struct task *t; /* Check if specified task already exists. */ if (task_lookup(task) != NULL) return EINVAL; if (!(t = malloc(sizeof(struct task)))) return ENOMEM; memset(t, 0, sizeof(struct task)); t->task = task; strcpy(t->cwd, "/"); mutex_init(&t->lock); TASK_LOCK(); list_insert(&task_table[TASKHASH(task)], &t->link); TASK_UNLOCK(); *pt = t; return 0; }
void task_dump(void) { #ifdef DEBUG_VFS list_t head, n; struct task *t; int i; TASK_LOCK(); dprintf("Dump file data\n"); dprintf(" task opens cwd\n"); dprintf(" -------- ------- ------------------------------\n"); for (i = 0; i < TASK_MAXBUCKETS; i++) { head = &task_table[i]; for (n = list_first(head); n != head; n = list_next(n)) { t = list_entry(n, struct task, link); dprintf(" %08x %7x %s\n", (int)t->task, t->nopens, t->cwd); } } dprintf("\n"); TASK_UNLOCK(); #endif }
int msgQSmReceive ( SM_MSG_Q_ID smMsgQId, /* message queue from which to receive*/ char * buffer, /* buffer to receive message */ UINT maxNBytes, /* length of buffer */ int timeout /* ticks to wait */ ) { SM_MSG_NODE volatile * pMsg; int bytesReturned; int level; SM_MSG_Q_ID volatile smMsgQIdv = (SM_MSG_Q_ID volatile) smMsgQId; int temp; /* temp storage */ /* * even though maxNBytes is unsigned, check for < 0 to catch * possible caller errors */ if ((int) maxNBytes < 0) { 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_MSGQRECEIVE, smMsgQId, buffer, maxNBytes, timeout, 0,4); CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = smMsgQIdv->verify; /* PCI bridge bug [SPR 68844]*/ if (SM_OBJ_VERIFY (smMsgQIdv) != OK) { TASK_UNLOCK (); return (ERROR); } /* block until a message is available */ if (semSmTake (&smMsgQId->msgQSem, timeout) != OK) { smMsgQId->recvTimeouts = htonl (ntohl (smMsgQId->recvTimeouts) + 1); TASK_UNLOCK (); return (ERROR); } /* a message was available before timeout, get it */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->msgQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQReceive", (char *) &smMsgQId->msgQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } pMsg = (SM_MSG_NODE volatile *) smDllGet (&smMsgQId->msgQ); SM_OBJ_LOCK_GIVE (&smMsgQId->msgQLock, level);/* release lock */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ temp = pMsg->msgLength; /* PCI bridge bug [SPR 68844]*/ bytesReturned = min (ntohl (pMsg->msgLength), maxNBytes); bcopy (SM_MSG_NODE_DATA (pMsg), buffer, bytesReturned); /* now give back message to free queue */ if (SM_OBJ_LOCK_TAKE (&smMsgQId->freeQLock, &level) != OK) { smObjTimeoutLogMsg ("msgQReceive", (char *) &smMsgQId->freeQLock); TASK_UNLOCK (); return (ERROR); /* can't take lock */ } smDllAdd (&smMsgQId->freeQ, (SM_DL_NODE *) pMsg); SM_OBJ_LOCK_GIVE (&smMsgQId->freeQLock, level);/* release lock */ /* now give free queue semaphore */ if (semSmGive (&smMsgQId->freeQSem) != OK) { TASK_UNLOCK (); return (ERROR); } TASK_UNLOCK (); return (bytesReturned); }
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); }
STATUS msgQSend(FAST MSG_Q_ID msgQId, char* buffer, FAST UINT nBytes, int timeout, int priority) { FAST MSG_NODE* pMsg; if(!INT_CONTEX()) { TASK_LOCK(); } else { /* ISR not pend */ if(0 != timeout) { return (ERROR); } } restart: if(!IS_CLASS(msgQId, msgQClassId)) { if(!INT_CONTEX()) { TASK_UNLOCK(); } return (ERROR); } if(nBytes > msgQId->maxMsgLength) { if(!INT_CONTEX()) { TASK_UNLOCK(); } return (ERROR); } pMsg = (MSG_NODE*)qJobGet(msgQId, &msgQId->freeQ, timeout); if(pMsg == (MSG_NODE*)NONE) { /* TODO recalc timeout and why? */ goto restart; } if(pMsg == NULL) { msgQId->sendTimeouts++; if(!INT_CONTEX()) { TASK_UNLOCK(); } return (ERROR); } pMsg->msgLength = nBytes; memcpy(MSG_NODE_DATA(pMsg), buffer, (int)nBytes); if(OK != qJobPut(msgQId, &msgQId->msgQ, &pMsg->node, priority)) { if(!INT_CONTEX()) { TASK_UNLOCK(); } return (ERROR); } if(!INT_CONTEX()) { TASK_UNLOCK(); } return (OK); }