xref: /minix/minix/lib/libbdev/call.c (revision 83133719)
1 /* libbdev - asynchronous call structure management */
2 
3 #include <minix/drivers.h>
4 #include <minix/bdev.h>
5 #include <assert.h>
6 
7 #include "const.h"
8 #include "type.h"
9 #include "proto.h"
10 
11 static bdev_call_t *calls[NR_CALLS];
12 
13 bdev_call_t *bdev_call_alloc(int count)
14 {
15 /* Allocate a call structure.
16  */
17   bdev_call_t *call;
18   bdev_id_t id;
19 
20   for (id = 0; id < NR_CALLS; id++)
21 	if (calls[id] == NULL)
22 		break;
23 
24   if (id == NR_CALLS)
25 	return NULL;
26 
27   call = malloc(sizeof(bdev_call_t) +
28 	sizeof(call->gvec[0]) * (count - 1) +
29 	sizeof(call->vec[0]) * count);
30 
31   if (call == NULL)
32 	return NULL;
33 
34   call->id = id;
35   call->vec = (iovec_t *) &call->gvec[count];
36 
37   calls[id] = call;
38 
39   return call;
40 }
41 
42 void bdev_call_free(bdev_call_t *call)
43 {
44 /* Free a call structure.
45  */
46 
47   assert(calls[call->id] == call);
48 
49   calls[call->id] = NULL;
50 
51   free(call);
52 }
53 
54 bdev_call_t *bdev_call_get(bdev_id_t id)
55 {
56 /* Retrieve a call structure by request number.
57  */
58 
59   if (id < 0 || id >= NR_CALLS)
60 	return NULL;
61 
62   return calls[id];
63 }
64 
65 bdev_call_t *bdev_call_find(dev_t dev)
66 {
67 /* Find the first asynchronous request for the given device, if any.
68  */
69   bdev_id_t id;
70 
71   for (id = 0; id < NR_CALLS; id++)
72 	if (calls[id] != NULL && calls[id]->dev == dev)
73 		return calls[id];
74 
75   return NULL;
76 }
77 
78 bdev_call_t *bdev_call_iter_maj(dev_t dev, bdev_call_t *call,
79 	bdev_call_t **next)
80 {
81 /* Iterate over all asynchronous requests for a major device. This function
82  * must be safe even if the returned call structure is freed.
83  */
84   bdev_id_t id;
85   int major;
86 
87   major = major(dev);
88 
89   /* If this is the first invocation, find the first match. Otherwise, take the
90    * call we found to be next in the last invocation, which may be NULL.
91    */
92   if (call == NULL) {
93 	for (id = 0; id < NR_CALLS; id++)
94 		if (calls[id] != NULL && major(calls[id]->dev) == major)
95 			break;
96 
97 	if (id == NR_CALLS)
98 		return NULL;
99 
100 	call = calls[id];
101   } else {
102 	if ((call = *next) == NULL)
103 		return NULL;
104   }
105 
106   /* Look for the next match, if any. */
107   *next = NULL;
108 
109   for (id = call->id + 1; id < NR_CALLS; id++) {
110 	if (calls[id] != NULL && major(calls[id]->dev) == major) {
111 		*next = calls[id];
112 
113 		break;
114 	}
115   }
116 
117   return call;
118 }
119