/* * Advance the receive pointer for the queue to the next message. */ void gru_free_message(struct gru_message_queue_desc *mqd, void *mesg) { struct message_queue *mq = mqd->mq; struct message_header *mhdr = mq->next; void *next, *pnext; int half = -1; int lines = mhdr->lines; if (lines == 2) restore_present2(mhdr, MQS_EMPTY); mhdr->present = MQS_EMPTY; pnext = mq->next; next = pnext + GRU_CACHE_LINE_BYTES * lines; if (next == mq->limit) { next = mq->start; half = 1; } else if (pnext < mq->start2 && next >= mq->start2) { half = 0; } if (half >= 0) mq->hstatus[half] = 1; mq->next = next; }
/* * Get next message from message queue. Return NULL if no message * present. User must call next_message() to move to next message. * rmq message queue */ void *gru_get_next_message(struct gru_message_queue_desc *mqd) { struct message_queue *mq = mqd->mq; struct message_header *mhdr = mq->next; int present = mhdr->present; /* skip NOOP messages */ while (present == MQS_NOOP) { gru_free_message(mqd, mhdr); mhdr = mq->next; present = mhdr->present; } /* Wait for both halves of 2 line messages */ if (present == MQS_FULL && mhdr->lines == 2 && get_present2(mhdr) == MQS_EMPTY) present = MQS_EMPTY; if (!present) { STAT(mesq_receive_none); return NULL; } if (mhdr->lines == 2) restore_present2(mhdr, mhdr->present2); STAT(mesq_receive); return mhdr; }
/* * Send a message to a message queue * cb GRU control block to use to send message * mq message queue * mesg message. ust be vaddr within a GSEG * bytes message size (<= 2 CL) */ int gru_send_message_gpa(unsigned long mq, void *mesg, unsigned int bytes) { struct message_header *mhdr; void *cb; void *dsr; int istatus, clines, ret; STAT(mesq_send); BUG_ON(bytes < sizeof(int) || bytes > 2 * GRU_CACHE_LINE_BYTES); clines = DIV_ROUND_UP(bytes, GRU_CACHE_LINE_BYTES); if (gru_get_cpu_resources(bytes, &cb, &dsr)) return MQE_BUG_NO_RESOURCES; memcpy(dsr, mesg, bytes); mhdr = dsr; mhdr->present = MQS_FULL; mhdr->lines = clines; if (clines == 2) { mhdr->present2 = get_present2(mhdr); restore_present2(mhdr, MQS_FULL); } do { ret = MQE_OK; gru_mesq(cb, mq, gru_get_tri(mhdr), clines, IMA); istatus = gru_wait(cb); if (istatus != CBS_IDLE) ret = send_message_failure(cb, mq, dsr, clines); } while (ret == MQIE_AGAIN); gru_free_cpu_resources(cb, dsr); if (ret) STAT(mesq_send_failed); return ret; }