]> git.saurik.com Git - apple/libc.git/blob - mach.subproj/mach_subsystem_join.c
Libc-166.tar.gz
[apple/libc.git] / mach.subproj / mach_subsystem_join.c
1 /*
2 * @OSF_COPYRIGHT@
3 */
4
5 #include <string.h> /* To get NULL */
6 #include <mach/boolean.h>
7 #include <mach/kern_return.h>
8 #include <mach/rpc.h>
9
10 #if 0
11 # include <stdio.h>
12 # define debug(x) printf x
13 #else
14 # define debug(x)
15 #endif
16
17 /*
18 * Routine: mach_subsystem_join
19 * Purpose:
20 * Create a new subsystem, suitable for registering with
21 * mach_subsystem_create, that consists of the union of
22 * the routines of subsys_1 and subsys_2.
23 *
24 * Warning:
25 * If there is a big gap between the routine numbers of
26 * the two subsystems, a correspondingly large amount of
27 * space will be wasted in the new subsystem.
28 */
29 rpc_subsystem_t
30 mach_subsystem_join(rpc_subsystem_t subsys_1, /* First input subsystem */
31 rpc_subsystem_t subsys_2, /* Second input subsystem */
32 unsigned int *num_bytes_p, /* Size of output subsystem */
33 void *(*malloc_func)(int) /* Allocation routine to use */
34 )
35 {
36 rpc_subsystem_t sp, subsys_new;
37 int num_routines, num_args, num_bytes;
38 int i, j;
39 struct routine_arg_descriptor *ap;
40 struct routine_descriptor *rp;
41
42 /* Make sure the two routine number ranges do not overlap:
43 */
44 if (subsys_1->start <= subsys_2->start && subsys_1->end > subsys_2->start
45 ||
46 subsys_2->start <= subsys_1->start && subsys_2->end > subsys_1->start)
47 return NULL;
48
49 /* Arrange that subsys_1 is the subsystem with the lower numbered
50 * routines:
51 */
52 if (subsys_2->start < subsys_1->start ||
53 subsys_2->end < subsys_1->end) {
54 /* Exchange the two input subsystem pointers: */
55 sp = subsys_2; subsys_2 = subsys_1; subsys_1 = sp;
56 }
57
58 debug(("subys_join: Lower subsys: (%d, %d); Higher subsys: (%d, %d)\n",
59 subsys_1->start, subsys_1->end, subsys_2->start, subsys_2->end));
60
61 /*
62 * Calculate size needed for new subsystem and allocate it:
63 */
64 num_args = 0;
65 sp = subsys_1;
66 do {
67 int nr;
68
69 nr = sp->end - sp->start;
70 num_routines += nr;
71
72 for (rp = &sp->routine[0]; rp < &sp->routine[nr]; rp++) {
73 /* Make sure this routine is non-null: */
74 if (rp->impl_routine != NULL)
75 num_args += rp->descr_count;
76 }
77 if (sp == subsys_2)
78 break;
79 sp = subsys_2;
80 } while (1);
81 num_routines = subsys_2->end - subsys_1->start;
82
83 /* A struct rpc_subsystem, which is just a template for a real
84 * subsystem descriptor, has one dummy routine descriptor in it
85 * and one arg descriptor, so we have to subtract these out, when
86 * calculating room for the routine and arg arrays:
87 */
88 num_bytes = sizeof(struct rpc_subsystem) +
89 (num_routines - 1) * sizeof(struct routine_descriptor) +
90 (num_args - 1) * sizeof(struct routine_arg_descriptor);
91
92 debug(("subys_new: %x; #routines: %d; #args: %d; #bytes: %d\n",
93 subsys_new, num_routines, num_args, num_bytes));
94
95 subsys_new = (rpc_subsystem_t) (*malloc_func)(num_bytes);
96 if (subsys_new == NULL)
97 return NULL;
98
99 /* Initialize the new subsystem, then copy the lower-numbered
100 * subsystem into the new subsystem, then the higher-numbered one:
101 */
102
103 subsys_new->subsystem = NULL; /* Reserved for system use */
104 subsys_new->start = subsys_1->start;
105 subsys_new->end = subsys_2->end;
106 subsys_new->maxsize = subsys_1->maxsize > subsys_2->maxsize ?
107 subsys_1->maxsize : subsys_2->maxsize;
108 subsys_new->base_addr = (vm_address_t)subsys_new;
109
110 /* Point ap at the beginning of the arg_descriptors for the
111 * joined subystem, i.e. just after the end of the combined
112 * array of routine descriptors:
113 */
114 ap = (struct routine_arg_descriptor *)
115 &(subsys_new->routine[num_routines]);
116 rp = &(subsys_new->routine[0]);
117
118 /* Copy subsys_1 into subsys_new: */
119 debug(("subys_join: Copying lower subsys: rp=%x, ap=%x\n", rp, ap));
120 for (i = 0; i < subsys_1->end - subsys_1->start; i++, rp++) {
121 *rp = subsys_1->routine[i];
122 if (rp->impl_routine != NULL) {
123 rp->arg_descr = ap;
124 for (j = 0; j < rp->descr_count; j++)
125 *ap++ = subsys_1->routine[i].arg_descr[j];
126 } else
127 rp->arg_descr = NULL;
128 }
129
130 /* Fill in the gap, if any, between subsys_1 routine numbers
131 * and subsys_2 routine numbers:
132 */
133 for (i = subsys_1->end; i < subsys_2->start; i++, rp++) {
134 rp->impl_routine = NULL;
135 rp->arg_descr = NULL;
136 }
137
138 /* Copy subsys_2 into subsys_new: */
139 debug(("subys_join: Copying higher subsys: rp=%x, ap=%x\n", rp, ap));
140 for (i = 0; i < subsys_2->end - subsys_2->start; i++, rp++) {
141 *rp = subsys_2->routine[i];
142 if (rp->impl_routine != NULL) {
143 rp->arg_descr = ap;
144 for (j = 0; j < rp->descr_count; j++)
145 *ap++ = subsys_2->routine[i].arg_descr[j];
146 } else
147 rp->arg_descr = NULL;
148 }
149 debug(("subys_join: Done: rp=%x, ap=%x\n", rp, ap));
150
151 *num_bytes_p = num_bytes;
152 return subsys_new;
153 }