Files
Arquivotheca.SunOS-4.1.4/etc/rpc.lockd/prot_msg.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

289 lines
6.2 KiB
C

#ifndef lint
static char sccsid[] = "@(#)prot_msg.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* prot_msg.c
* consists all routines handle msg passing
*/
#include "prot_lock.h"
#include "prot_time.h"
extern int debug;
extern int grace_period;
extern int msg_len;
extern remote_result res_working;
char *xmalloc();
msg_entry *klm_msg; /* ptr last msg to klm in msg queue */
msg_entry *msg_q; /* head of msg queue */
/*
* retransmitted search through msg_queue to determine if "a" is
* retransmission of a previously received msg;
* it returns the addr of the msg entry if "a" is found
* otherwise, it returns NULL
*/
msg_entry *
retransmitted(a, proc)
struct reclock *a;
int proc;
{
msg_entry *msgp;
msgp = msg_q;
while (msgp != NULL) {
if (same_lock(msgp->req, &(a->lck.lox)) || simi_lock(msgp->req, a)) {
/*
* 5 is the constant diff between rpc calls and msg
* passing
*/
if ((msgp->proc == NLM_LOCK_RECLAIM &&
(proc == KLM_LOCK || proc == NLM_LOCK_MSG)) ||
msgp->proc == proc + 5 || msgp->proc == proc)
return (msgp);
}
msgp = msgp->nxt;
}
return (NULL);
}
/*
* match response's cookie with msg req
* either return msgp or NULL if not found
*/
msg_entry *
search_msg(resp)
remote_result *resp;
{
msg_entry *msgp;
struct reclock *req;
msgp = msg_q;
while (msgp != NULL) {
req = msgp->req;
if (obj_cmp(&req->cookie, &resp->cookie))
return (msgp);
msgp = msgp->nxt;
}
return (NULL);
}
/*
* add a to msg queue; called from nlm_call: when rpc call is succ and reply is needed
* proc is needed for sending back reply later
* if case of error, NULL is returned;
* otherwise, the msg entry is returned
*/
msg_entry *
queue(a, proc)
struct reclock *a;
int proc;
{
msg_entry *msgp;
if ((msgp = (msg_entry *) xmalloc(msg_len)) == NULL)
return (NULL);
bzero((char *) msgp, msg_len);
msgp->req = a;
msgp->proc = proc;
msgp->t.exp = 1;
/* insert msg into msg queue */
if (msg_q == NULL) {
msgp->nxt = msgp->prev = NULL;
msg_q = msgp;
/* turn on alarm only when there are msgs in msg queue */
if (grace_period == 0)
(void) alarm(LM_TIMEOUT);
}
else {
msgp->nxt = msg_q;
msgp->prev = NULL;
msg_q->prev = msgp;
msg_q = msgp;
}
if ( proc != NLM_LOCK_RECLAIM )
klm_msg = msgp; /* record last msg to klm */
return (msgp);
}
/*
* dequeue remove msg from msg_queue;
* and deallocate space obtained from malloc
* lockreq is release only if a->rel == 1;
*/
dequeue(msgp)
msg_entry *msgp;
{
if (debug)
printf("enter dequeue (msgp %x) ...\n", msgp);
/*
* First, delete msg from msg queue since dequeue(),
* FREELOCK() and dequeue_lock() are recursive.
*/
if (msgp->prev != NULL)
msgp->prev->nxt = msgp->nxt;
else
msg_q = msgp->nxt;
if (msgp->nxt != NULL)
msgp->nxt->prev = msgp->prev;
if (msgp->req != NULL)
release_reclock(msgp->req);
if (msgp->reply != NULL)
release_res(msgp->reply);
bzero((char *) msgp, sizeof (*msgp));
free((char *) msgp);
if (debug)
printf("msg_q %x\n", msg_q);
}
/*
* Find a reclock and dequeue it. But do not actually free reclock here.
*/
void
dequeue_lock(a)
struct reclock *a;
{
msg_entry *msgp;
msg_entry *next_msgp;
msgp = msg_q;
while (msgp != NULL) {
next_msgp= msgp->nxt;
if (a == msgp->req) {
msgp->req = NULL; /* don't free here; caller does it */
dequeue(msgp);
}
msgp = next_msgp;
}
return;
}
/*
* if resp is not NULL, add reply to msg_entyr and reply if msg is last req;
* otherwise, reply working
*/
add_reply(msgp, resp )
msg_entry *msgp;
remote_result *resp;
{
if (debug)
printf("enter add_reply ...\n");
if ( resp != NULL) {
msgp->t.curr = 0; /* reset timer counter to record old msg */
msgp->reply = resp;
if (debug) {
if (klm_msg && klm_msg->req)
printf("klm_msg->req=%x\n", klm_msg->req);
if (msgp && msgp->req)
printf("msgp->req=%x reply_stat=%d\n",
msgp->req, msgp->reply->stat.stat);
}
if (klm_msg && msgp && klm_msg->req == msgp->req) {
/* reply immed */
klm_reply(msgp->proc, resp);
/*
* prevent timer routine reply "working" to already
* replied req
*/
klm_msg = NULL;
if (resp->lstat != blocking) {
/* we don't want to free req if its a lock */
/* request as the lock is queued for */
/* monitor */
if ((msgp->req != NULL) &&
(msgp->proc != NLM_LOCK &&
msgp->proc != NLM_LOCK_MSG) &&
(msgp->proc != NLM_LOCK_RECLAIM))
/* set free reclock */
msgp->req->rel = 1;
dequeue(msgp);
}
}
} else { /* res == NULL, used by xtimer */
if (debug)
printf(" RESP == NULL\n");
if (klm_msg == msgp) {
if (debug)
printf("xtimer reply to (%x): ", msgp->req);
klm_reply(msgp->proc, &res_working);
klm_msg = NULL;
}
}
}
/*
* signal handler:
* wake up periodically to check retransmiting status and reply to last req
*/
xtimer()
{
msg_entry *msgp, *next;
if (debug)
printf("\nalarm! enter xtimer:\n");
if (grace_period > 0) {
/* reduce the remaining grace period */
grace_period--;
if (grace_period == 0) {
if (debug)
printf("**********end of grace period\n");
/* remove proc == klm_xxx in msg queue */
next = msg_q;
while ((msgp = next) != NULL) {
next = msgp->nxt;
if (msgp->proc == KLM_LOCK ||
msgp->proc == KLM_UNLOCK ||
msgp->proc == KLM_TEST ||
msgp->proc == KLM_CANCEL) {
if (debug)
printf("remove grace period msg (%x) from msg queue\n", msgp);
if (msgp->req != NULL) /* set free reclock */
msgp->req->rel = 1;
dequeue(msgp);
}
}
}
}
next = msg_q;
while ((msgp = next) != NULL) {
next = msgp->nxt;
if (msgp->reply == NULL) { /* check for retransimssion */
if (msgp->proc != KLM_LOCK) {
/* KLM_LOCK is for local blocked locks */
if (msgp->t.exp == msgp->t.curr) {
/* retransmit */
if (debug)
printf("xtimer retransmit: ");
(void) nlm_call(msgp->proc, msgp->req, 1);
msgp->t.curr = 0;
msgp->t.exp = 2 * msgp->t.exp;
/* double timeout period */
if (msgp->t.exp > MAX_LM_TIMEOUT_COUNT){
msgp->t.exp = MAX_LM_TIMEOUT_COUNT;
}
}
else /* increment current count */
msgp->t.curr++;
}
}
}
if (grace_period != 0 || msg_q != NULL)
(void) alarm(LM_TIMEOUT);
}