XINU
rdsread.c
Go to the documentation of this file.
1 /* rdsread.c - rdsread */
2 
3 #include <xinu.h>
4 
5 /*------------------------------------------------------------------------
6  * rdsread - Read a block from a remote disk
7  *------------------------------------------------------------------------
8  */
10  struct dentry *devptr, /* Entry in device switch table */
11  char *buff, /* Buffer to hold disk block */
12  int32 blk /* Block number of block to read*/
13  )
14 {
15  struct rdscblk *rdptr; /* Pointer to control block */
16  struct rdbuff *bptr; /* Pointer to buffer possibly */
17  /* in the request list */
18  struct rdbuff *nptr; /* Pointer to "next" node on a */
19  /* list */
20  struct rdbuff *pptr; /* Pointer to "previous" node */
21  /* on a list */
22  struct rdbuff *cptr; /* Pointer that walks the cache */
23 
24  /* If device not currently in use, report an error */
25 
26  rdptr = &rdstab[devptr->dvminor];
27  if (rdptr->rd_state != RD_OPEN) {
28  return SYSERR;
29  }
30 
31  /* Ensure rdsprocess is runnning */
32 
33  if ( ! rdptr->rd_comruns ) {
34  rdptr->rd_comruns = TRUE;
35  resume(rdptr->rd_comproc);
36  }
37 
38  /* Search the cache for specified block */
39 
40  bptr = rdptr->rd_chnext;
41  while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) {
42  if (bptr->rd_blknum == blk) {
43  if (bptr->rd_status == RD_INVALID) {
44  break;
45  }
46  memcpy(buff, bptr->rd_block, RD_BLKSIZ);
47  return OK;
48  }
49  bptr = bptr->rd_next;
50  }
51 
52  /* Search the request list for most recent occurrence of block */
53 
54  bptr = rdptr->rd_rtprev; /* Start at tail of list */
55 
56  while (bptr != (struct rdbuff *)&rdptr->rd_rhnext) {
57  if (bptr->rd_blknum == blk) {
58 
59  /* If most recent request for block is write, copy data */
60 
61  if (bptr->rd_op == RD_OP_WRITE) {
62  memcpy(buff, bptr->rd_block, RD_BLKSIZ);
63  return OK;
64  }
65  break;
66  }
67  bptr = bptr->rd_prev;
68  }
69 
70  /* Allocate a buffer and add read request to tail of req. queue */
71 
72  bptr = rdsbufalloc(rdptr);
73  bptr->rd_op = RD_OP_READ;
74  bptr->rd_refcnt = 1;
75  bptr->rd_blknum = blk;
76  bptr->rd_status = RD_INVALID;
77  bptr->rd_pid = getpid();
78 
79  /* Insert new request into list just before tail */
80 
81  pptr = rdptr->rd_rtprev;
82  rdptr->rd_rtprev = bptr;
83  bptr->rd_next = pptr->rd_next;
84  bptr->rd_prev = pptr;
85  pptr->rd_next = bptr;
86 
87  /* Prepare to receive message when read completes */
88 
89  recvclr();
90 
91  /* Signal the semaphore to start communication */
92 
93  signal(rdptr->rd_reqsem);
94 
95  /* Block to wait for a message */
96 
97  bptr = (struct rdbuff *)receive();
98  if (bptr == (struct rdbuff *)SYSERR) {
99  return SYSERR;
100  }
101  memcpy(buff, bptr->rd_block, RD_BLKSIZ);
102  bptr->rd_refcnt--;
103  if (bptr->rd_refcnt <= 0) {
104 
105  /* Look for previous item in cache with the same block */
106  /* number to see if this item was only being kept */
107  /* until pending read completed */
108 
109  cptr = rdptr->rd_chnext;
110  while (cptr != bptr) {
111  if (cptr->rd_blknum == blk) {
112 
113  /* Unlink from cache */
114 
115  pptr = bptr->rd_prev;
116  nptr = bptr->rd_next;
117  pptr->rd_next = nptr;
118  nptr->rd_prev = pptr;
119 
120  /* Add to the free list */
121 
122  bptr->rd_next = rdptr->rd_free;
123  rdptr->rd_free = bptr;
124  break;
125  }
126  cptr = cptr->rd_next;
127  }
128  }
129  return OK;
130 }
#define RD_OP_WRITE
Definition: rdisksys.h:43
#define RD_OPEN
Definition: rdisksys.h:37
#define RD_BLKSIZ
Definition: rdisksys.h:9
sid32 rd_reqsem
Definition: rdisksys.h:92
int32 rd_op
Definition: rdisksys.h:58
int32 dvminor
Definition: conf.h:8
全てのシステムヘッダファイルをインクルードする。
#define SYSERR
処理が失敗した場合
Definition: kernel.h:79
int32 rd_status
Definition: rdisksys.h:62
#define OK
処理が成功した場合
Definition: kernel.h:77
#define RD_OP_READ
Definition: rdisksys.h:42
umsg32 receive(void)
メッセージの受信を待ち、受信後にreceive()の呼び出し者にメッセージを返す。
Definition: receive.c:17
pid32 rd_comproc
Definition: rdisksys.h:89
Definition: conf.h:6
bool8 rd_comruns
Definition: rdisksys.h:90
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
umsg32 recvclr(void)
受信メッセージをクリアし、待機している場合はメッセージを返す。
Definition: recvclr.c:14
struct rdscblk rdstab[]
Definition: rdsinit.c:11
int int32
符号あり32ビット整数(int)
Definition: kernel.h:11
devcall rdsread(struct dentry *devptr, char *buff, int32 blk)
Definition: rdsread.c:9
int32 rd_refcnt
Definition: rdisksys.h:59
struct rdbuff * rd_next
Definition: rdisksys.h:56
pri16 resume(pid32)
プロセスを休止状態(サスペンド)からREADY状態に遷移させる。
Definition: resume.c:20
pid32 getpid(void)
現在実行中のプロセスIDを返す。
Definition: getpid.c:11
pid32 rd_pid
Definition: rdisksys.h:63
struct rdbuff * rdsbufalloc(struct rdscblk *)
Definition: rdsbufalloc.c:9
struct rdbuff * rd_rtprev
Definition: rdisksys.h:76
struct rdbuff * rd_ctnext
Definition: rdisksys.h:82
struct rdbuff * rd_chnext
Definition: rdisksys.h:80
syscall signal(sid32)
セマフォにシグナルを送り、待機プロセスがある場合は解除する。
Definition: signal.c:18
int32 rd_state
Definition: rdisksys.h:69
int32 devcall
デバイスコール関数 返り値の型
Definition: kernel.h:49
char rd_block[RD_BLKSIZ]
Definition: rdisksys.h:65
uint32 rd_blknum
Definition: rdisksys.h:61
void * memcpy(void *, const void *, int32)
メモリAの領域(source)からメモリBの領域(Destination)にN Byteコピーする。
Definition: memcpy.c:13
#define RD_INVALID
Definition: rdisksys.h:49