mach_subsystem_join.c [plain text]
#include <string.h>
#include <mach/boolean.h>
#include <mach/kern_return.h>
#include <mach/rpc.h>
#if 0
# include <stdio.h>
# define debug(x) printf x
#else
# define debug(x)
#endif
rpc_subsystem_t
mach_subsystem_join(rpc_subsystem_t subsys_1,
rpc_subsystem_t subsys_2,
unsigned int *num_bytes_p,
void *(*malloc_func)(int)
)
{
rpc_subsystem_t sp, subsys_new;
int num_routines, num_args, num_bytes;
int i, j;
struct routine_arg_descriptor *ap;
struct routine_descriptor *rp;
if (subsys_1->start <= subsys_2->start && subsys_1->end > subsys_2->start
||
subsys_2->start <= subsys_1->start && subsys_2->end > subsys_1->start)
return NULL;
if (subsys_2->start < subsys_1->start ||
subsys_2->end < subsys_1->end) {
sp = subsys_2; subsys_2 = subsys_1; subsys_1 = sp;
}
debug(("subys_join: Lower subsys: (%d, %d); Higher subsys: (%d, %d)\n",
subsys_1->start, subsys_1->end, subsys_2->start, subsys_2->end));
num_args = 0;
sp = subsys_1;
do {
int nr;
nr = sp->end - sp->start;
num_routines += nr;
for (rp = &sp->routine[0]; rp < &sp->routine[nr]; rp++) {
if (rp->impl_routine != NULL)
num_args += rp->descr_count;
}
if (sp == subsys_2)
break;
sp = subsys_2;
} while (1);
num_routines = subsys_2->end - subsys_1->start;
num_bytes = sizeof(struct rpc_subsystem) +
(num_routines - 1) * sizeof(struct routine_descriptor) +
(num_args - 1) * sizeof(struct routine_arg_descriptor);
debug(("subys_new: %x; #routines: %d; #args: %d; #bytes: %d\n",
subsys_new, num_routines, num_args, num_bytes));
subsys_new = (rpc_subsystem_t) (*malloc_func)(num_bytes);
if (subsys_new == NULL)
return NULL;
subsys_new->subsystem = NULL;
subsys_new->start = subsys_1->start;
subsys_new->end = subsys_2->end;
subsys_new->maxsize = subsys_1->maxsize > subsys_2->maxsize ?
subsys_1->maxsize : subsys_2->maxsize;
subsys_new->base_addr = (vm_address_t)subsys_new;
ap = (struct routine_arg_descriptor *)
&(subsys_new->routine[num_routines]);
rp = &(subsys_new->routine[0]);
debug(("subys_join: Copying lower subsys: rp=%x, ap=%x\n", rp, ap));
for (i = 0; i < subsys_1->end - subsys_1->start; i++, rp++) {
*rp = subsys_1->routine[i];
if (rp->impl_routine != NULL) {
rp->arg_descr = ap;
for (j = 0; j < rp->descr_count; j++)
*ap++ = subsys_1->routine[i].arg_descr[j];
} else
rp->arg_descr = NULL;
}
for (i = subsys_1->end; i < subsys_2->start; i++, rp++) {
rp->impl_routine = NULL;
rp->arg_descr = NULL;
}
debug(("subys_join: Copying higher subsys: rp=%x, ap=%x\n", rp, ap));
for (i = 0; i < subsys_2->end - subsys_2->start; i++, rp++) {
*rp = subsys_2->routine[i];
if (rp->impl_routine != NULL) {
rp->arg_descr = ap;
for (j = 0; j < rp->descr_count; j++)
*ap++ = subsys_2->routine[i].arg_descr[j];
} else
rp->arg_descr = NULL;
}
debug(("subys_join: Done: rp=%x, ap=%x\n", rp, ap));
*num_bytes_p = num_bytes;
return subsys_new;
}