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