XINU
rdsprocess.c
Go to the documentation of this file.
1 /* rdsprocess.c - rdsprocess */
2 
3 #include <xinu.h>
4 
5 /*------------------------------------------------------------------------
6  * rdsprocess - High-priority background process that repeatedly
7  * extracts an item from the request queue, sends the
8  * request to the remote disk server, and handles the
9  * response, including caching responses blocks
10  *------------------------------------------------------------------------
11  */
12 void rdsprocess (
13  struct rdscblk *rdptr /* Ptr to device control block */
14  )
15 {
16  struct rd_msg_wreq msg; /* Message to be sent */
17  /* (includes data area) */
18  struct rd_msg_rres resp; /* Buffer to hold response */
19  /* (includes data area) */
20  int32 retval; /* Return value from rdscomm */
21  char *idto; /* Ptr to ID string copy */
22  char *idfrom; /* Ptr into ID string */
23  struct rdbuff *bptr; /* Ptr to buffer at the head of */
24  /* the request queue */
25  struct rdbuff *nptr; /* Ptr to next buffer on the */
26  /* request queue */
27  struct rdbuff *pptr; /* Ptr to previous buffer */
28  struct rdbuff *qptr; /* Ptr that runs along the */
29  /* request queue */
30  int32 i; /* Loop index */
31 
32  while (TRUE) { /* Do forever */
33 
34  /* Wait until the request queue contains a node */
35  wait(rdptr->rd_reqsem);
36  bptr = rdptr->rd_rhnext;
37 
38  /* Use operation in request to determine action */
39 
40  switch (bptr->rd_op) {
41 
42  case RD_OP_READ:
43 
44  /* Build a read request message for the server */
45 
46  msg.rd_type = htons(RD_MSG_RREQ); /* Read request */
47  msg.rd_status = htons(0);
48  msg.rd_seq = 0; /* Rdscomm fills in an entry */
49  idto = msg.rd_id;
50  memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero */
51  idfrom = rdptr->rd_id;
52  while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */
53  ;
54  }
55 
56  /* Send the message and receive a response */
57 
58  retval = rdscomm((struct rd_msg_hdr *)&msg,
59  sizeof(struct rd_msg_rreq),
60  (struct rd_msg_hdr *)&resp,
61  sizeof(struct rd_msg_rres),
62  rdptr );
63 
64  /* Check response */
65 
66  if ( (retval == SYSERR) || (retval == TIMEOUT) ||
67  (ntohs(resp.rd_status) != 0) ) {
68  panic("Failed to contact remote disk server");
69  }
70 
71  /* Copy data from the reply into the buffer */
72 
73  for (i=0; i<RD_BLKSIZ; i++) {
74  bptr->rd_block[i] = resp.rd_data[i];
75  }
76 
77  /* Unlink buffer from the request queue */
78 
79  nptr = bptr->rd_next;
80  pptr = bptr->rd_prev;
81  nptr->rd_prev = bptr->rd_prev;
82  pptr->rd_next = bptr->rd_next;
83 
84  /* Insert buffer in the cache */
85 
86  pptr = (struct rdbuff *) &rdptr->rd_chnext;
87  nptr = pptr->rd_next;
88  bptr->rd_next = nptr;
89  bptr->rd_prev = pptr;
90  pptr->rd_next = bptr;
91  nptr->rd_prev = bptr;
92 
93  /* Initialize reference count */
94 
95  bptr->rd_refcnt = 1;
96 
97  /* Signal the available semaphore */
98 
99  signal(rdptr->rd_availsem);
100 
101  /* Send a message to waiting process */
102 
103  send(bptr->rd_pid, (uint32)bptr);
104 
105  /* If other processes are waiting to read the */
106  /* block, notify them and remove the request */
107 
108  qptr = rdptr->rd_rhnext;
109  while (qptr != (struct rdbuff *)&rdptr->rd_rtnext) {
110  if (qptr->rd_blknum == bptr->rd_blknum) {
111  bptr->rd_refcnt++;
112  send(qptr->rd_pid,(uint32)bptr);
113 
114  /* Unlink request from queue */
115 
116  pptr = qptr->rd_prev;
117  nptr = qptr->rd_next;
118  pptr->rd_next = bptr->rd_next;
119  nptr->rd_prev = bptr->rd_prev;
120 
121  /* Move buffer to the free list */
122 
123  qptr->rd_next = rdptr->rd_free;
124  rdptr->rd_free = qptr;
125  signal(rdptr->rd_availsem);
126  break;
127  }
128  qptr = qptr->rd_next;
129  }
130  break;
131 
132  case RD_OP_WRITE:
133 
134  /* Build a write request message for the server */
135 
136  msg.rd_type = htons(RD_MSG_WREQ); /* Write request*/
137  msg.rd_blk = bptr->rd_blknum;
138  msg.rd_status = htons(0);
139  msg.rd_seq = 0; /* Rdscomb fills in an entry */
140  idto = msg.rd_id;
141  memset(idto, NULLCH, RD_IDLEN);/* Initialize ID to zero */
142  idfrom = rdptr->rd_id;
143  while ( (*idto++ = *idfrom++) != NULLCH ) { /* Copy ID */
144  ;
145  }
146  for (i=0; i<RD_BLKSIZ; i++) {
147  msg.rd_data[i] = bptr->rd_block[i];
148  }
149 
150  /* Unlink buffer from request queue */
151 
152  nptr = bptr->rd_next;
153  pptr = bptr->rd_prev;
154  pptr->rd_next = nptr;
155  nptr->rd_prev = pptr;
156 
157  /* Insert buffer in the cache */
158 
159  pptr = (struct rdbuff *) &rdptr->rd_chnext;
160  nptr = pptr->rd_next;
161  bptr->rd_next = nptr;
162  bptr->rd_prev = pptr;
163  pptr->rd_next = bptr;
164  nptr->rd_prev = bptr;
165 
166  /* Declare that buffer is eligible for reuse */
167 
168  bptr->rd_refcnt = 0;
169  signal(rdptr->rd_availsem);
170 
171  /* Send the message and receive a response */
172 
173  retval = rdscomm((struct rd_msg_hdr *)&msg,
174  sizeof(struct rd_msg_wreq),
175  (struct rd_msg_hdr *)&resp,
176  sizeof(struct rd_msg_wres),
177  rdptr );
178 
179  /* Check response */
180 
181  if ( (retval == SYSERR) || (retval == TIMEOUT) ||
182  (ntohs(resp.rd_status) != 0) ) {
183  panic("failed to contact remote disk server");
184  }
185  break;
186 
187  case RD_OP_SYNC:
188 
189  /* Send a message to the waiting process */
190 
191  send(bptr->rd_pid, OK);
192 
193  /* Unlink buffer from the request queue */
194 
195  nptr = bptr->rd_next;
196  pptr = bptr->rd_prev;
197  nptr->rd_prev = bptr->rd_prev;
198  pptr->rd_next = bptr->rd_next;
199 
200  /* Insert buffer into the free list */
201 
202  bptr->rd_next = rdptr->rd_free;
203  rdptr->rd_free = bptr;
204  signal(rdptr->rd_availsem);
205  break;
206  }
207  }
208 }
209 
210 
211 
212 
#define RD_OP_WRITE
Definition: rdisksys.h:43
#define RD_MSG_RREQ
Definition: rdisksys.h:120
#define RD_BLKSIZ
Definition: rdisksys.h:9
sid32 rd_reqsem
Definition: rdisksys.h:92
int32 rd_op
Definition: rdisksys.h:58
全てのシステムヘッダファイルをインクルードする。
#define SYSERR
処理が失敗した場合
Definition: kernel.h:79
struct rdbuff * rd_rtnext
Definition: rdisksys.h:75
#define RD_IDLEN
Definition: rdisksys.h:29
#define OK
処理が成功した場合
Definition: kernel.h:77
sid32 rd_availsem
Definition: rdisksys.h:91
syscall send(pid32, umsg32)
プロセスにメッセージを送信し、受信側が待機状態の場合はREADY状態にする。
Definition: send.c:21
#define RD_OP_READ
Definition: rdisksys.h:42
#define RD_MSG_WREQ
Definition: rdisksys.h:123
#define TIMEOUT
システムコールがタイムアウトした場合
Definition: kernel.h:83
struct rdbuff * rd_free
Definition: rdisksys.h:87
struct rdbuff * rd_prev
Definition: rdisksys.h:57
struct rdbuff * rd_rhnext
Definition: rdisksys.h:73
#define TRUE
Boolean True(1)
Definition: kernel.h:65
void rdsprocess(struct rdscblk *rdptr)
Definition: rdsprocess.c:12
#define RD_OP_SYNC
Definition: rdisksys.h:44
int int32
符号あり32ビット整数(int)
Definition: kernel.h:11
int32 rd_refcnt
Definition: rdisksys.h:59
struct rdbuff * rd_next
Definition: rdisksys.h:56
void * memset(void *, const int, int32)
指定のByteブロックに対して、同じ値をNバイト分書き込む。
Definition: memset.c:13
#define ntohs(x)
Definition: prototypes.h:622
pid32 rd_pid
Definition: rdisksys.h:63
void panic(char *)
Panic状態に陥った旨のメッセージを表示し、全てのプロセスを停止させる。
Definition: panic.c:12
status rdscomm(struct rd_msg_hdr *, int32, struct rd_msg_hdr *, int32, struct rdscblk *)
Definition: rdscomm.c:11
struct rdbuff * rd_chnext
Definition: rdisksys.h:80
syscall wait(sid32)
Definition: wait.c:9
syscall signal(sid32)
セマフォにシグナルを送り、待機プロセスがある場合は解除する。
Definition: signal.c:18
char rd_id[RD_IDLEN]
Definition: rdisksys.h:70
unsigned int uint32
符号なし32ビット整数(unsigned int)
Definition: kernel.h:15
#define htons(x)
Definition: prototypes.h:619
char rd_block[RD_BLKSIZ]
Definition: rdisksys.h:65
uint32 rd_blknum
Definition: rdisksys.h:61
#define NULLCH
NULL文字(NULL終端)
Definition: kernel.h:70