32 |
|
|
33 |
#define KERNEL_MSG_SIZE (256-4) |
#define KERNEL_MSG_SIZE (256-4) |
34 |
|
|
|
static struct kmem_cache *atomic_cache; |
|
35 |
static struct kmem_cache *kmsg_cache; |
static struct kmem_cache *kmsg_cache; |
36 |
|
|
|
/* Copy a message into a kernel buffer must be done in a "atomic" |
|
|
manner. If we fail somewhere along the road the task state must |
|
|
be unchanged. |
|
|
|
|
|
To do this we have hold a list of atomic elements that will be |
|
|
executed when we have checked all rights and permissions. */ |
|
|
|
|
|
enum ipc_atomic_type |
|
|
{ |
|
|
IPC_ATOMIC_PORT_REMOVE, /* Remove port from task. */ |
|
|
IPC_ATOMIC_PORT_REF /* ??? */ |
|
|
}; |
|
|
|
|
|
struct ipc_atomic |
|
|
{ |
|
|
enum ipc_atomic_type type; |
|
|
|
|
|
union { |
|
|
rtmk_port_t name; |
|
|
struct ipc_port *port; |
|
|
} params; |
|
|
}; |
|
|
|
|
|
/* Add a new element to array of atomic operations. */ |
|
|
|
|
|
static void atomic_add (struct ipc_atomic ***atomics, int *n_atomics, |
|
|
int *n_max_atomics, enum ipc_atomic_type type, ...); |
|
|
|
|
|
/* Execute atomic operations specified in ATOMICS. */ |
|
|
|
|
|
static void atomic_execute (struct task *task, struct ipc_atomic **atomics, |
|
|
int n_atomics); |
|
|
|
|
|
|
|
37 |
/* Initialize kernel messages. */ |
/* Initialize kernel messages. */ |
38 |
|
|
39 |
void |
void |
40 |
ipc_kmsg_init (void) |
ipc_kmsg_init (void) |
41 |
{ |
{ |
42 |
kmsg_cache = kmem_cache_create ("ipc kmsg cache", KERNEL_MSG_SIZE, 0); |
kmsg_cache = kmem_cache_create ("ipc kmsg cache", KERNEL_MSG_SIZE, 0); |
43 |
atomic_cache = kmem_cache_create ("ipc atomic cache", |
assert (kmsg_cache); |
|
sizeof (struct ipc_atomic), 0); |
|
|
assert (kmsg_cache && atomic_cache); |
|
44 |
} |
} |
45 |
|
|
46 |
/* Allocate a new kernel message with SIZE bytes payload. |
/* Allocate a new kernel message with SIZE bytes payload. |
430 |
return KERN_SUCCESS; |
return KERN_SUCCESS; |
431 |
} |
} |
432 |
|
|
|
|
|
|
/* ??? convenience function for expanding an atomic element array. */ |
|
|
|
|
|
static inline void expand_atomic_array (struct ipc_atomic ***atomics, |
|
|
int *n_atomics, int *n_max_atomics) |
|
|
{ |
|
|
if (*atomics == 0) |
|
|
{ |
|
|
*n_max_atomics = 16; |
|
|
*n_atomics = 0; |
|
|
*atomics = |
|
|
(struct ipc_atomic **) kmem_zalloc (*n_max_atomics |
|
|
* sizeof (struct ipc_atomic *)); |
|
|
} |
|
|
|
|
|
if (*n_atomics == *n_max_atomics) |
|
|
{ |
|
|
struct ipc_atomic **new_atomics; |
|
|
|
|
|
*n_max_atomics <<= 1; |
|
|
|
|
|
new_atomics = |
|
|
(struct ipc_atomic **) kmem_zalloc (*n_max_atomics |
|
|
* sizeof (struct ipc_atomic *)); |
|
|
memcpy (*atomics, new_atomics, |
|
|
*n_atomics * sizeof (struct ipc_atomic *)); |
|
|
|
|
|
kmem_mfree (*atomics); |
|
|
*atomics = new_atomics; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* Add an atomic element to list of elements (ATOMIC). */ |
|
|
|
|
|
static void |
|
|
atomic_add (struct ipc_atomic ***atomics, int *n_atomics, |
|
|
int *n_max_atomics, enum ipc_atomic_type type, ...) |
|
|
{ |
|
|
struct ipc_atomic *atomic; |
|
|
va_list ap; |
|
|
|
|
|
expand_atomic_array (atomics, n_atomics, n_max_atomics); |
|
|
|
|
|
va_start (ap, type); |
|
|
|
|
|
atomic = kmem_cache_alloc (atomic_cache); |
|
|
atomic->type = type; |
|
|
|
|
|
switch (type) |
|
|
{ |
|
|
case IPC_ATOMIC_PORT_REMOVE: |
|
|
{ |
|
|
rtmk_port_t name = va_arg (ap, rtmk_port_t); |
|
|
atomic->params.name = name; |
|
|
break; |
|
|
} |
|
|
|
|
|
case IPC_ATOMIC_PORT_REF: |
|
|
{ |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
*atomics[*n_atomics++] = atomic; |
|
|
va_end (ap); |
|
|
} |
|
|
|
|
|
/* Execute an array of atomic elements. This also releases all |
|
|
memory allocated by "atomic_add". */ |
|
|
|
|
|
static void |
|
|
atomic_execute (struct task *task, struct ipc_atomic **atomics, |
|
|
int n_atomics) |
|
|
{ |
|
|
struct ipc_atomic *atomic; |
|
|
|
|
|
int i; |
|
|
|
|
|
for (i = 0; i < n_atomics; i++) |
|
|
{ |
|
|
atomic = atomics [i]; |
|
|
|
|
|
switch (atomic->type) |
|
|
{ |
|
|
case IPC_ATOMIC_PORT_REMOVE: |
|
|
break; |
|
|
case IPC_ATOMIC_PORT_REF: |
|
|
break; |
|
|
} |
|
|
kmem_cache_free (atomic_cache, atomic); |
|
|
} |
|
|
kmem_mfree (atomics); |
|
|
} |
|