/[rtmk]/rtmk/ipc-kmsg.c
ViewVC logotype

Diff of /rtmk/ipc-kmsg.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.11 by jrydberg, Sat Feb 23 01:41:01 2002 UTC revision 1.12 by jrydberg, Sun Feb 24 23:09:48 2002 UTC
# Line 30  Foundation, Inc., 59 Temple Place - Suit Line 30  Foundation, Inc., 59 Temple Place - Suit
30    
31  #include "ipc-kmsg.h"  #include "ipc-kmsg.h"
32    
33  #ifndef WORD_ALIGN  /* Notes about the message intermediate format:
34    
35       Port names are resolved into pointers to port structures (ie ipc_port).
36       Out-of-line memory is held by a holding map if it not maps against
37       port rights.  If it do, hold a kernel buffer with port structures.  */
38    
39    #ifndef WORD_ALIGN /* ??? move to tm.h */
40  # define WORD_ALIGN(X) (((X) + 3) & ~3)  # define WORD_ALIGN(X) (((X) + 3) & ~3)
41  #endif  #endif
42    
# Line 162  copyin_header (struct task *task, struct Line 168  copyin_header (struct task *task, struct
168    return KERN_SUCCESS;    return KERN_SUCCESS;
169  }  }
170    
171    
172    
173    /* Convert kernel message in KMSG to intermediate format stored on
174       the message queue.  Ports names are resolved into ports, and
175       out-of-line memory is held by a holding map.  */
176    kern_return_t
177    convert_kernel_to_intermediate (struct ipc_kmsg *kmsg)
178    {
179      struct rtmk_msg_type_long *type_long;
180      struct rtmk_msg_type *type;
181      vm_offset_t start, end;
182    
183      start = (vm_offset_t)  (&kmsg->header + 1);
184      end   = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length;
185    
186      /* Loop through all type elements of the message body.  */
187    
188      while (start < end)
189        {
190          unsigned int header_size, number, length, size;
191          vm_offset_t data_ptr;
192    
193          /* If we we have a long format message type header we
194             get length and number fields from long structure. */
195          type = (struct rtmk_msg_type *) start;
196          size = type->msgt_length;
197    
198          if (LIKELY (! type->msgt_long))
199            {
200              header_size = sizeof (struct rtmk_msg_type);
201              number = type->msgt_number;
202            }
203          else
204            {
205              type_long = (struct rtmk_msg_type_long *) type;
206              header_size = sizeof (struct rtmk_msg_type_long);
207              number = type_long->msgtl_number;
208            }
209    
210          /* DATA_PTR points to where the inline data begins.  */
211          data_ptr = ((vm_offset_t) type) + header_size;
212    
213          /* Calulcate length of data (either inline or out-of-line).  */
214          length = ((number * size) + 7) >> 3;
215    
216          /* For out-of-line memory we create a holding map and store
217             it in the position for the data pointer.  */
218          if (! type->msgt_inline)
219            {
220              /* The sender should supply ready-made memory
221                 for us, so we don't need to do anything.  */
222            }
223    
224          /* Calulcat length of inline data and skip over it.   */
225          if (LIKELY (type->msgt_inline))
226            start = WORD_ALIGN (data_ptr + length);
227          else
228            start = data_ptr + sizeof (rtmk_port_t *); /* ??? ptr */
229        }
230      return KERN_SUCCESS;
231    }
232    
233    
234    /* Convert user message in KMSG to intermediate format stored on
235       the message queue.  Ports names are resolved into ports, and
236       out-of-line memory is held by a holding map.  */
237    kern_return_t
238    convert_user_to_intermediate (struct task *task, struct ipc_kmsg *kmsg)
239    {
240      struct rtmk_msg_type_long *type_long;
241      struct rtmk_msg_type *type;
242      vm_offset_t start, end;
243      kern_return_t kr;
244    
245      start = (vm_offset_t)  (&kmsg->header + 1);
246      end   = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length;
247    
248      /* Loop through all type elements of the message body.  */
249    
250      while (start < end)
251        {
252          unsigned int header_size, number, length, size, port_p, i;
253          struct ipc_entry *entry;
254          vm_offset_t data_ptr;
255    
256          /* If we we have a long format message type header we
257             get length and number fields from long structure. */
258          type = (struct rtmk_msg_type *) start;
259          size = type->msgt_length;
260    
261          if (LIKELY (! type->msgt_long))
262            {
263              header_size = sizeof (struct rtmk_msg_type);
264              number = type->msgt_number;
265            }
266          else
267            {
268              type_long = (struct rtmk_msg_type_long *) type;
269              header_size = sizeof (struct rtmk_msg_type_long);
270              number = type_long->msgtl_number;
271            }
272    
273          /* DATA_PTR points to where the inline data begins.  */
274          data_ptr = ((vm_offset_t) type) + header_size;
275    
276          /* Calulcate length of data (either inline or out-of-line).  */
277          length = ((number * size) + 7) >> 3;
278    
279          port_p = RTMK_MSG_TYPE_PORT_ANY (type->msgt_type);
280    
281          /* ??? it is very likely that it's inline data.  */
282          if (LIKELY (type->msgt_inline))
283            {
284              if (port_p)
285                {
286                  rtmk_port_t *port_name;
287                  struct ipc_port *port;
288              
289                  port_name = (rtmk_port_t *) data_ptr;
290                  
291                  /* Loop through all elements and take actions upon them.  */
292                  for (i = 0; i < number; i++)
293                    {
294                      if (port_name [i])
295                        {
296                          /* ??? not lookup, do copyin  */
297                          kr = ipc_object_lookup (task->ipc_object, port_name [i],
298                                                  & entry);
299                          if (kr != KERN_SUCCESS)
300                            return kr;
301                          
302                          port = entry->ie_port;
303                        }
304                      else
305                        port = 0;
306              
307                      /* Store pointer to port structure in place for port name. */
308                      port_name [i] = (rtmk_port_t) port;
309                    }
310                }
311            }
312    
313          /* Out-of-line memory:  */
314          else
315            {
316              if (port_p)
317                {
318                  struct ipc_port **ports, *port;
319                  rtmk_port_t *port_name;
320    
321                  /* We allocate a internal buffer for the port structures.
322                     We copy in user data from address space into that buffer.  */
323                  ports = (struct ipc_port **) kmem_malloc (length);
324                  COPYIN ((void *) ports, *(void **) data_ptr, length);
325    
326                  port_name = (rtmk_port_t *) ports;
327    
328                  /* Loop through all port names and take actions.  */
329                  for (i = 0; i < number; i++)
330                    {
331                      if (port_name [i])
332                        {
333                          kr = ipc_object_lookup (task->ipc_object, port_name [i],
334                                                  & entry);
335                          if (kr != KERN_SUCCESS)
336                            return kr;
337                          port = entry->ie_port;
338                        }
339                      else
340                        port = 0;
341              
342                      /* Store pointer to port structure in place for port name. */
343                      port_name [i] = (rtmk_port_t) port;
344                    }
345                }
346    
347              /* For out-of-line memory we create a holding map and store
348                 it in the position for the data pointer.  */
349              else
350                {
351                  struct vm_map *map;
352    
353                  if (length != 0)
354                    {
355                      map = vm_map_copyin (task->map, *(vm_offset_t *) data_ptr,
356                                           length, type->msgt_deallocate);
357                      assert (map);
358                      *(vm_offset_t *) data_ptr = (vm_offset_t) map;
359                    }
360                }
361            }
362    
363          /* Calulcat length of inline data and skip over it.   */
364          if (LIKELY (type->msgt_inline))
365            start = WORD_ALIGN (data_ptr + length);
366          else
367            start = data_ptr + sizeof (rtmk_port_t *); /* ??? ptr */
368        }
369      return KERN_SUCCESS;
370    }
371    
372    
373    
374    /* Convert intermediate message stored in KMSG to user format
375       where ports is translated into port names and out-of-line memory
376       is mapped into TASK's address space.  */
377    kern_return_t
378    convert_intermediate_to_user (struct task *task, struct ipc_kmsg *kmsg)
379    {
380      struct rtmk_msg_type_long *type_long;
381      struct rtmk_msg_type *type;
382      vm_offset_t start, end;
383      kern_return_t kr;
384    
385      start = (vm_offset_t)  (&kmsg->header + 1);
386      end   = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length;
387    
388      /* Loop through all type elements of the message body.  */
389    
390      while (start < end)
391        {
392          unsigned int header_size, number, length, size, port_p, i;
393          vm_offset_t data_ptr;
394    
395          /* If we we have a long format message type header we
396             get length and number fields from long structure. */
397          type = (struct rtmk_msg_type *) start;
398          size = type->msgt_length;
399    
400          if (LIKELY (! type->msgt_long))
401            {
402              header_size = sizeof (struct rtmk_msg_type);
403              number = type->msgt_number;
404            }
405          else
406            {
407              type_long = (struct rtmk_msg_type_long *) type;
408              header_size = sizeof (struct rtmk_msg_type_long);
409              number = type_long->msgtl_number;
410            }
411    
412          /* DATA_PTR points to where the inline data begins.  */
413          data_ptr = ((vm_offset_t) type) + header_size;
414    
415          /* Calulcate length of data (either inline or out-of-line).  */
416          length = ((number * size) + 7) >> 3;
417    
418          port_p = RTMK_MSG_TYPE_PORT_ANY (type->msgt_type);
419    
420          if (LIKELY (type->msgt_inline))
421            {
422              if (port_p)
423                {
424                  struct ipc_port **port;
425                  rtmk_port_t *port_name;
426                  
427                  /* ??? ports can not be in out-of-line memory?  */
428                  assert (type->msgt_inline == true);
429                  
430                  port_name = (rtmk_port_t *) data_ptr;
431                  port      = (struct ipc_port **) data_ptr;
432                  
433                  /* Loop through all elements and take actions upon them.  */
434                  for (i = 0; i < number; i++)
435                    {        
436                      if (port [i])
437                        {
438                          kr = ipc_object_copyout (task->ipc_object, port [i],
439                                                   type->msgt_type,
440                                                   & port_name [i]);
441                          if (kr != KERN_SUCCESS)
442                            return kr;
443                        }
444                      else
445                        port_name [i] = RTMK_PORT_NULL;
446                    }
447                }
448            }
449    
450          /* For out-of-line memory we create a holding map and store
451             it in the position for the data pointer.  */
452          else
453            {
454              /* If the out-of-line is port rights, the ports is held
455                 by a kernel buffer stored at *DATA_PTR.  */
456              if (port_p)
457                {
458                  struct ipc_port **port = *(struct ipc_port ***) data_ptr;
459                  rtmk_port_t *port_name = *(rtmk_port_t **) data_ptr;
460                  vm_offset_t addr;
461    
462                  /* Loop through all elements and take actions upon them.  */
463                  for (i = 0; i < number; i++)
464                    {        
465                      if (port [i])
466                        {
467                          kr = ipc_object_copyout (task->ipc_object, port [i],
468                                                   type->msgt_type,
469                                                   & port_name [i]);
470                          if (kr != KERN_SUCCESS)
471                            return kr;
472                        }
473                    }
474    
475                  /* Here: Port names are in PORT_NAME.  What we need to do;
476                     allocate memory in TASK's addres space and copy out.  */
477                  kr = vm_map_allocate (task->map, & addr, vm_round_page (length),
478                                        0, VM_PROT_ALL, VM_PROT_ALL,
479                                        VM_INHERIT_COPY, 1);
480                  assert (kr == KERN_SUCCESS);
481    
482                  COPYOUT ((void *) addr, (void *) port_name, length);
483                  *(vm_offset_t *) data_ptr = addr;
484    
485                  kmem_mfree (port);
486                }
487              else
488                {
489                  assert (0);
490                }
491            }
492    
493          /* Calulcat length of inline data and skip over it.   */
494          if (LIKELY (type->msgt_inline))
495            start = WORD_ALIGN (data_ptr + length);
496          else
497            start = data_ptr + sizeof (vm_offset_t);
498        }
499      return KERN_SUCCESS;
500    }
501    
502  /* Convert message stored in KMSG to intermedate format where port  /* Convert message stored in KMSG to intermedate format where port
503     names are resolved to ipc_port structures and out-of-line data     names are resolved to ipc_port structures and out-of-line data
504     in mapped into kernel address space.  */     in mapped into kernel address space.  */
# Line 389  ipc_kmsg_copyout (struct task *task, str Line 726  ipc_kmsg_copyout (struct task *task, str
726    if (kr)    if (kr)
727      return kr;      return kr;
728    
729    kr = copyout_body (task, kmsg);    kr = convert_intermediate_to_user (task, kmsg);
730    if (kr)    if (kr)
731      return kr;      return kr;
732    
# Line 422  ipc_kmsg_copyin_kernel (struct task *tas Line 759  ipc_kmsg_copyin_kernel (struct task *tas
759    kmsg->complex_p   = true;    kmsg->complex_p   = true;
760    kmsg->intratask_p = false;    kmsg->intratask_p = false;
761    
762    /* ??? since we do not support OOL memory from kernel yet,    convert_kernel_to_intermediate (kmsg);
         we can just return here since we are done.  */  
763    return KERN_SUCCESS;    return KERN_SUCCESS;
764  }  }
765    
# Line 467  ipc_kmsg_copyin (struct task *task, stru Line 803  ipc_kmsg_copyin (struct task *task, stru
803    if (kr)    if (kr)
804      return kr;      return kr;
805    
806    kr = copyin_body (task, kmsg);    kr = convert_user_to_intermediate (task, kmsg);
807    if (kr)    if (kr)
808      return kr;      return kr;
809    

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26