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

Diff of /rtmk/ipc-object.c

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

revision 1.9 by jrydberg, Sun Feb 24 23:09:48 2002 UTC revision 1.10 by jrydberg, Wed Mar 27 00:13:45 2002 UTC
# Line 17  Foundation, Inc., 59 Temple Place - Suit Line 17  Foundation, Inc., 59 Temple Place - Suit
17    
18  #include "tm.h"  #include "tm.h"
19  #include "trace.h"  #include "trace.h"
20    #include "task.h"
21    
22  #include "ipc-object.h"  #include "ipc-object.h"
23  #include "ipc-port.h"  #include "ipc-port.h"
# Line 113  ipc_object_create (void) Line 114  ipc_object_create (void)
114    
115  /* Convenience function for removing ENTRY from OBJECT.  */  /* Convenience function for removing ENTRY from OBJECT.  */
116    
117  static inline bool  static bool
118  remove_entry (struct ipc_object *object, struct ipc_entry *entry)  remove_entry (struct ipc_object *object, struct ipc_entry *entry)
119  {  {
120    if (IE_BITS_RIGHTS (entry->ie_bits) != RTMK_PORT_TYPE_SEND_ONCE)    if (IE_BITS_RIGHTS (entry->ie_bits) & RTMK_PORT_TYPE_SEND_RIGHTS)
121      ipc_reverse_remove (entry);      ipc_reverse_remove (entry);
122    
123    if (entry->ie_key <= MTABLERIGHTS)    if (entry->ie_key <= MTABLERIGHTS)
# Line 238  ipc_entry_alloc_name (struct ipc_object Line 239  ipc_entry_alloc_name (struct ipc_object
239    return KERN_SUCCESS;    return KERN_SUCCESS;
240  }  }
241    
242    /* Deallocate ENTRY (port right name is ENTRY->ie_key) from
243  /* Convenience function for reserving space in OBJECT.  */     OBJECT.  We also remove from reverse-lookup table.  */
244  static bool  kern_return_t
245  reserve_entry (struct ipc_object *object, struct ipc_entry **entryp,  ipc_entry_dealloc (struct ipc_object *object,
246                 rtmk_port_t *namep)                     struct ipc_entry *entry)
247  {  {
248    rtmk_port_t low, high, key;    if (IE_BITS_RIGHTS (entry->ie_bits) != RTMK_PORT_TYPE_SEND_ONCE)
249    struct ipc_entry *entry;      ipc_reverse_remove (entry);
   bool result;  
     
   /* First of all we try to reserve in the table.  If we don't  
      succeed with that we go on and try with the splay-tree.  */  
   
   result = ipc_table_reserve (&object->tbl, entryp, namep);  
   if (result == true)  
     return true;  
     
   /* Optimize for the case when the splay tree is empty.  */  
   if (object->splay_tree.root == 0)  
     {  
       entry = (struct ipc_entry *) kmem_cache_alloc (ipc_entry_cache);  
       entry->ie_key = MTABLERIGHTS + 1;  
   
       *namep  = MTABLERIGHTS + 1;  
       *entryp = entry;  
   
       /* We can now insert it into the splay-tree */  
       entry->ie_left = entry->ie_right = 0;  
       object->splay_tree.root = entry;  
       return true;  
     }  
     
   /* Get the first entry.  */  
   
   ipc_splay_tree_first (&object->splay_tree, &entry);    
   key = entry->ie_key;  
   result = true;  
   
   while (result == true)  
     {  
       rtmk_port_t diff;  
         
       result = ipc_splay_tree_bounds (&object->splay_tree, key,  
                                       &low, &high);  
         
       /* If RESULT is false, then we know this was the last entry in  
          tree.  So what we do is: NAME = ++LAST .  */  
   
       if (result == false)  
         {  
           key = high + 1;  
           break;          
         }  
   
       diff = key - low;  
       if (diff >= 2)  
         {  
           key = low + 1;  
           goto allocate_and_return;  
         }  
             
       diff = high - key;  
       if (diff >= 2)  
         {  
           key = key + 1;  
           goto allocate_and_return;  
         }  
         
       result = true;  
       key = high;            
     }  
       
  allocate_and_return:  
   
   entry = (struct ipc_entry *) kmem_cache_alloc (ipc_entry_cache);  
   entry->ie_key = key;  
   *entryp = entry;  
   *namep  = key;  
   
   /* We can now insert it into the splay-tree */  
250    
251    ipc_splay_tree_insert (&object->splay_tree, key, entry);    if (entry->ie_key <= MTABLERIGHTS)
252    return true;      ipc_table_remove (&object->tbl, entry->ie_key);
253      else
254        ipc_splay_tree_delete_node (&object->splay_tree, entry->ie_key,
255                                    &entry);
256      kmem_cache_free (ipc_entry_cache, entry);
257      return KERN_SUCCESS;
258  }  }
259    
260    
# Line 347  ipc_reserve_entry_named (struct ipc_obje Line 281  ipc_reserve_entry_named (struct ipc_obje
281    entry->ie_key    = name;    entry->ie_key    = name;
282    entry->ie_port   = port;    entry->ie_port   = port;
283    entry->ie_object = object;    entry->ie_object = object;
284    entry->ie_urefs  = 1;    entry->ie_urefs  = 0;
285    
286    /* Set valid bit and right for port.  */    /* Set valid bit and right for port.  */
287    entry->ie_bits = IE_BITS_VALID | RTMK_PORT_TYPE_RECEIVE;    entry->ie_bits = IE_BITS_VALID;
   
288    
289    /* We can insert it into the revese lookup hash table.  */          /* We can insert it into the revese lookup hash table.  */      
290    ipc_reverse_insert (object, entry);    ipc_reverse_insert (object, entry);
# Line 363  ipc_reserve_entry_named (struct ipc_obje Line 296  ipc_reserve_entry_named (struct ipc_obje
296    return true;    return true;
297  }  }
298    
299  /* Create right for PORT in OBJECT.  MSGT describes what right the  
300     object should have to the port.  Name is returned in NAMEP.  */  /* Try to locate entry named NAME in OBJECT.  Return pointer to
301           entry structure in ENTRYP if found.  Normal kernel return code.  */
302  kern_return_t  kern_return_t
303  ipc_object_copyout (struct ipc_object *object, struct ipc_port *port,  ipc_object_lookup (struct ipc_object *object, rtmk_port_t name,
304                      int msgt, rtmk_port_t *namep)                     struct ipc_entry **entryp)
305  {  {
306    bool sonce = false, result;    ipc_entry entry;
307    struct ipc_entry *entry;    bool result;
     
   /* SONCE is true if we should create send-once right.  */  
   
   if (msgt == RTMK_MSG_TYPE_MAKE_SEND_ONCE)  
     sonce = true;  
   
   /* If it's not a send once right we first look in the reverse  
      lookup table.  */  
308    
309    if (sonce == false    /* Try the "fast" lookup table first.  */
310        && ipc_reverse_lookup (object, port, &entry) == KERN_SUCCESS)    
311      if (name <= MTABLERIGHTS)
312      {      {
313        entry->ie_bits = entry->ie_bits | convert_name_to_right (msgt);        result = ipc_table_lookup (&object->tbl, name, entryp);
314        entry->ie_urefs++;        if (result == false)
315            return KERN_INVALID_NAME;    
       if (msgt == RTMK_MSG_TYPE_MAKE_SEND)  
         entry->ie_port->srights++;  
   
       *namep = entry->ie_key;  
316        return KERN_SUCCESS;        return KERN_SUCCESS;
317      }      }
318    
319    result = reserve_entry (object, &entry, namep);    /* We look in the splay-tree instead.  */
   assert (result);  
     
   /* Fill entry structure with needed information.  */  
   
   entry->ie_key = *namep;     /* XXX just in case */  
   entry->ie_port = port;  
   entry->ie_object = object;  
   entry->ie_urefs = 1;  
   
   /* Set valid bit and right for port.  */  
   
   entry->ie_bits = IE_BITS_VALID | convert_name_to_right (msgt);  
320    
321    /* If SONCE is false, then we can insert it into the revese lookup    entry = (ipc_entry) ipc_splay_tree_lookup (&object->splay_tree, name);
322       hash table aswell.  */          if (entry == 0)
323        return KERN_INVALID_NAME;
324    
325    if (sonce == false)    *entryp = entry;
326      ipc_reverse_insert (object, entry);    return KERN_SUCCESS;  
327    }
328    
329    /* Remove NAME for OBJECT.  Return IPC entry in *ENTRYP.  */
330    kern_return_t
331    ipc_object_remove (struct ipc_object *object,
332                       struct ipc_entry **entryp, rtmk_port_t name)
333    {
334      kern_return_t kr;
335      
336      kr = ipc_object_lookup (object, name, entryp);
337      if (kr != KERN_SUCCESS)
338        return kr;
339      remove_entry (object, *entryp);
340    return KERN_SUCCESS;    return KERN_SUCCESS;
341  }  }
342    
343  /* Copy right named NAME from OBJECT into kernel object space.  /* Copy right named NAME from OBJECT into kernel object space.
344     MSGT describes what type of right it is.  DEALLOCP is true     MSGT describes what type of right it is.  *PORTP holds
345     if *ENTRYP should be deallocated after it is used.  */     port that right NAME held.  */
346    
347  kern_return_t  kern_return_t
348  ipc_object_copyin (struct ipc_object *object, rtmk_port_t name,  ipc_object_copyin (struct ipc_object *object, rtmk_port_t name,
349                     int msgt, struct ipc_entry **entryp, bool *deallocp)                     int msgt, struct ipc_port **portp)
350  {  {
351    struct ipc_entry *entry;    kern_return_t kr = KERN_SUCCESS;
352    kern_return_t kr;    struct ipc_port *port;
353    bool sonce = false;    struct ipc_entry *ie;
354    
355    if (msgt == RTMK_MSG_TYPE_MOVE_SEND_ONCE)    kr = ipc_object_lookup (object, name, &ie);
356      sonce = true;    if (kr)
     
   kr = ipc_object_lookup (object, name, &entry);  
   if (kr != KERN_SUCCESS)  
357      return kr;      return kr;
358    *entryp = entry;    port = ie->ie_port;
359    
360      switch (msgt)
361        {
362        case RTMK_MSG_TYPE_MOVE_RECEIVE:
363          {
364            int bits = ie->ie_bits;
365            if (! (bits & RTMK_PORT_TYPE_RECEIVE))
366              goto invalid_right;
367    
368            thread_lock_write (&port->lock);
369            assert (port->rcvobject == object);
370            assert (port->rcvname == name);
371    
372            /* We move the receive right, but we still have send
373               right to the port.  We port into reverse lookup table.  */
374            if (bits & RTMK_PORT_TYPE_SEND)
375              {
376                assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_SEND_RECEIVE);
377                assert (ie->ie_urefs > 0);
378                assert (port->srights > 0);
379                
380                ipc_reverse_insert (object, ie);
381                port->ref_count++;
382              }
383            
384            /* No send right(s) to port.  We can deallocate entry.  */
385            else
386              {
387                assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_RECEIVE);
388                assert (ie->ie_urefs == 0);
389                ie->ie_port = 0;
390              }
391            ie->ie_bits &= ~RTMK_PORT_TYPE_RECEIVE;
392    
393            port->rcvobject = 0;
394            port->rcvname = RTMK_PORT_NULL;
395            thread_lock_unlock (&port->lock);
396    
397            *portp = port;
398            break;
399          }
400    
401        case RTMK_MSG_TYPE_COPY_SEND:
402          {
403            int bits = ie->ie_bits;
404            if (! (bits & RTMK_PORT_TYPE_SEND_RIGHTS))
405              goto invalid_right;
406    
407            assert (ie->ie_urefs > 0);
408            if ((bits & RTMK_PORT_TYPE_SEND) == 0)
409              {
410                assert(IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_SEND_ONCE);
411                assert(port->sorights > 0);
412                goto invalid_right;
413              }
414    
415            thread_lock_write (&port->lock);
416            assert (port->srights > 0);
417            port->ref_count++;
418            port->srights++;
419            thread_lock_unlock (&port->lock);
420    
421            *portp = port;
422            break;
423          }
424    
425        case RTMK_MSG_TYPE_MAKE_SEND:
426          {
427            int bits = ie->ie_bits;
428            if (! (bits & RTMK_PORT_TYPE_RECEIVE))
429              goto invalid_right;
430            
431            thread_lock_write (&port->lock);
432            assert (port->rcvobject == object);
433            assert (port->rcvname == name);
434    
435            port->ref_count++;
436            port->srights++;
437            port->msrights++;
438            thread_lock_unlock (&port->lock);
439    
440            *portp = port;
441            break;
442          }
443    
444        case RTMK_MSG_TYPE_MOVE_SEND:
445          {
446            int bits = ie->ie_bits;
447            if (! (bits & RTMK_PORT_TYPE_SEND))
448              goto invalid_right;
449            
450            thread_lock_write (&port->lock);
451            assert (ie->ie_urefs > 1);
452            assert (port->srights > 1);
453    
454            if (ie->ie_urefs == 1)
455              {
456                if (bits & RTMK_PORT_TYPE_RECEIVE)
457                  {
458                    assert (port->rcvname == name);
459                    assert (port->rcvobject == object);
460                    assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_SEND_RECEIVE);
461                    port->ref_count++;
462                  }
463                else
464                  {
465                    assert (IE_BITS_RIGHTS (bits)
466                            == RTMK_PORT_TYPE_SEND);
467                    ipc_reverse_remove (ie);
468                    ie->ie_port = 0;
469                  }
470                ie->ie_bits &= ~RTMK_PORT_TYPE_SEND;
471                ie->ie_urefs = 0;
472              }
473            else
474              {
475                port->srights++;
476                port->ref_count++;
477                ie->ie_urefs -= 1;
478              }
479            thread_lock_unlock (&port->lock);
480    
481            *portp = port;
482            break;
483          }
484    
485        case RTMK_MSG_TYPE_MOVE_SEND_ONCE:
486          {
487            int bits = ie->ie_bits;
488            if (! (bits & RTMK_PORT_TYPE_SEND_ONCE))
489              goto invalid_right;
490    
491            thread_lock_write (&port->lock);
492            assert (ie->ie_urefs > 0);
493            assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_SEND_ONCE);
494            assert (port->sorights > 0);
495            thread_lock_unlock (&port->lock);
496            
497            ie->ie_port = 0;
498            ie->ie_bits &= ~RTMK_PORT_TYPE_SEND_ONCE;
499    
500            *portp = port;
501            break;
502          }
503    
504        case RTMK_MSG_TYPE_MAKE_SEND_ONCE:
505          {
506            int bits = ie->ie_bits;
507            if (! (bits & RTMK_PORT_TYPE_RECEIVE))
508              goto invalid_right;
509    
510            thread_lock_write (&port->lock);
511            assert (port->rcvobject == object);
512            assert (port->rcvname == name);
513    
514            port->ref_count++;
515            port->sorights++;
516            thread_lock_unlock (&port->lock);
517    
518            *portp = port;
519            break;
520          }
521        }
522    
523    *deallocp = false;    if (IE_BITS_RIGHTS (ie->ie_bits) == RTMK_PORT_TYPE_NONE)
   if (sonce == true)  
524      {      {
525        (void) remove_entry (object, entry);        if (ie->ie_key <= MTABLERIGHTS)
526        *deallocp = true;          ipc_table_remove (&object->tbl, ie->ie_key);
527          else
528            ipc_splay_tree_delete_node (&object->splay_tree, ie->ie_key,
529                                        &ie);
530          kmem_cache_free (ipc_entry_cache, ie);
531      }      }
532      return kr;
533    
534    return KERN_SUCCESS;     invalid_right:
535      return KERN_INVALID_RIGHT;
536  }  }
537    
538  /* Try to locate entry named NAME in OBJECT.  Return pointer to  static kern_return_t
539     entry structure in ENTRYP if found.  Normal kernel return code.  */  right_copyout (struct ipc_object *object, struct ipc_port *port,
540                   int msgt, struct ipc_entry *entry, rtmk_port_t name)
 kern_return_t  
 ipc_object_lookup (struct ipc_object *object, rtmk_port_t name,  
                    struct ipc_entry **entryp)  
541  {  {
542    ipc_entry entry;    switch (msgt)
   bool result;  
   
   /* Try the "fast" lookup table first.  */  
     
   if (name <= MTABLERIGHTS)  
543      {      {
544        result = ipc_table_lookup (&object->tbl, name, entryp);      case RTMK_MSG_TYPE_COPY_SEND:
545        if (result == false)      case RTMK_MSG_TYPE_MAKE_SEND:
546          return KERN_INVALID_NAME;          case RTMK_MSG_TYPE_MOVE_SEND:
547        return KERN_SUCCESS;        {
548            int bits = entry->ie_bits;
549    
550            assert(port->srights > 0);
551    
552            if (bits & RTMK_PORT_TYPE_SEND)
553              {
554                assert (port->srights > 1);
555                assert (entry->ie_urefs > 0);
556    
557                port->srights--;
558                thread_lock_unlock (&port->lock);
559                ipc_port_release (port);
560              }
561            else if (bits & RTMK_PORT_TYPE_RECEIVE)
562              {
563                assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_RECEIVE);
564                assert (entry->ie_urefs == 0);
565                
566                /* transfer send right to entry */
567                thread_lock_unlock (&port->lock);
568                ipc_port_release (port);
569                ipc_reverse_insert (object, entry);
570              }
571            else
572              {
573                assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_NONE);
574                assert (entry->ie_urefs == 0);
575                
576                /* transfer send right and ref to entry */
577                thread_lock_unlock (&port->lock);
578                ipc_reverse_insert (object, entry);
579              }
580            entry->ie_bits = (bits | RTMK_PORT_TYPE_SEND);
581            entry->ie_urefs += 1;
582            break;
583          }
584    
585        case RTMK_MSG_TYPE_MAKE_SEND_ONCE:
586        case RTMK_MSG_TYPE_MOVE_SEND_ONCE:
587          {
588            int bits = entry->ie_bits;
589    
590            assert(IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_NONE);
591            assert(port->sorights > 0);
592            thread_lock_unlock (&port->lock);
593    
594            /* transfer send-once right and ref to entry */
595            entry->ie_bits = bits | (RTMK_PORT_TYPE_SEND_ONCE);
596            entry->ie_urefs = 1;
597            break;
598          }
599    
600        case RTMK_MSG_TYPE_MOVE_RECEIVE:
601          {
602            int bits = entry->ie_bits;
603    
604            assert (port->rcvname == RTMK_PORT_NULL);
605    
606            port->rcvname = name;
607            port->rcvobject = object;
608    
609            assert ((bits & RTMK_PORT_TYPE_RECEIVE) == 0);
610    
611            if (bits & RTMK_PORT_TYPE_SEND)
612              {
613                assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_SEND);
614                assert (entry->ie_urefs > 0);
615                assert (port->srights > 0);
616                
617                thread_lock_unlock (&port->lock);
618                ipc_port_release (port);
619                ipc_reverse_remove (entry);
620              }
621            else
622              {
623                assert (IE_BITS_RIGHTS (bits) == RTMK_PORT_TYPE_NONE);
624                assert (entry->ie_urefs == 0);
625    
626                /* transfer ref to entry */
627                thread_lock_unlock (&port->lock);
628              }
629            entry->ie_bits = bits | RTMK_PORT_TYPE_RECEIVE;
630            break;
631          }
632      }      }
633      return KERN_SUCCESS;
634    }
635    
   /* We look in the splay-tree instead.  */  
636    
637    entry = (ipc_entry) ipc_splay_tree_lookup (&object->splay_tree, name);  /* Inserts rights for PORT into OBJECT.  MSGT determines
638    if (entry == 0)     what type of right we should insert.   NAME is the right
639      return KERN_INVALID_NAME;     name in OBJECT.  If there's already a right for PORT
640       in OBJECT, NAME must match that rights name.  */
641    kern_return_t
642    ipc_object_copyout_name (struct ipc_object *object,
643                             struct ipc_port *port, int msgt,
644                             rtmk_port_t name)
645    {
646      struct ipc_entry *entry, *oentry;
647      kern_return_t kr;
648    
649    *entryp = entry;    kr = ipc_object_lookup (object, name, &oentry);
650    return KERN_SUCCESS;      if (kr == KERN_SUCCESS)
651        {
652          if (oentry->ie_port != port)
653            return KERN_INVALID_NAME;
654          entry = oentry;
655        }
656      else
657        {
658          kr = ipc_entry_alloc_name (object, &entry, name);
659          if (kr != KERN_SUCCESS)
660            return kr;
661          entry->ie_port = port;
662          entry->ie_key  = name;
663          entry->ie_object = object;
664          entry->ie_urefs = 0;
665          entry->ie_bits = IE_BITS_VALID;
666        }
667      thread_lock_write (&port->lock);
668      return right_copyout (object, port, msgt, entry, name);
669  }  }
670    
671  /* Insert rights for port PORT specified by MSGT into OBJECT.    /* Create right for PORT in OBJECT.  MSGT describes what right the
672     NAMEP is the name that we should use.  */     object should have to the port.  Name is returned in NAMEP.  */
673  kern_return_t  kern_return_t
674  ipc_object_insert (struct ipc_object *object, struct ipc_port *port,  ipc_object_copyout (struct ipc_object *object, struct ipc_port *port,
675                     int msgt, rtmk_port_t name)                      int msgt, rtmk_port_t *namep)
676  {  {
677    struct ipc_entry *entry;    struct ipc_entry *entry;
678    bool sonce = false;    kern_return_t kr;
   int err, right;  
     
   right = convert_name_to_right (msgt);  
   
   /* SONCE is true if we should create send-once right.  */  
   if (msgt == RTMK_MSG_TYPE_MAKE_SEND_ONCE  
       || msgt == RTMK_MSG_TYPE_MOVE_SEND_ONCE)  
     sonce = true;  
679    
680    /* If the target already holds send or receive rights for    for (;;)
      the port, then name should denote those rights in the target.   */  
   if (ipc_reverse_lookup (object, port, &entry) == KERN_SUCCESS)  
681      {      {
682        if (entry->ie_key != name)        if ((msgt != RTMK_MSG_TYPE_MAKE_SEND_ONCE
683          return KERN_RIGHT_EXISTS;             && msgt != RTMK_MSG_TYPE_MOVE_SEND_ONCE))
   
       switch (right)  
684          {          {
685          case RTMK_PORT_TYPE_SEND:            kr = ipc_reverse_lookup (object, port, &entry);
686            port->srights++;            if (kr == KERN_SUCCESS)
687            break;              {
688          case RTMK_PORT_TYPE_RECEIVE:                thread_lock_write (&port->lock);
689            assert (0);                break;
690            break;              }
   
         case RTMK_PORT_TYPE_SEND_ONCE:  
           port->sorights++;  
           break;  
691          }          }
         
       entry->ie_urefs++;  
       entry->ie_bits = entry->ie_bits | right;  
       return KERN_SUCCESS;        
     }  
692    
693    /* Allocate entry in OBJECT.  This also checks if NAME already        kr = ipc_entry_alloc (object, &entry, namep);
694       exists.  ENTRY contains no data (not even key).  */        if (kr)
695    err = ipc_entry_alloc_name (object, &entry, name);          return kr;
696    if (err)  
697      return err;        thread_lock_write (&port->lock);
698          entry->ie_port = port;
699          entry->ie_key = *namep;
700          entry->ie_urefs = 0;
701          entry->ie_bits = IE_BITS_VALID;
702          entry->ie_object = object;
703          break;
704        }
705      *namep = entry->ie_key;
706    
707      /* This unlocks port.  */
708      return right_copyout (object, port, msgt, entry, *namep);
709    }
710    
711    /* Fill entry structure with needed information.  */  
712    entry->ie_key    = name;  /* Copyout right PORT.  PORT is destination for a
713    entry->ie_port   = port;     message.  Name of right is returned in *NAMEP.  */
714    entry->ie_object = object;  kern_return_t
715    ipc_object_copyout_dest (struct ipc_object *object,
716                             struct ipc_port *port, int msgt_name,
717                             rtmk_port_t *namep)
718    {
719      rtmk_port_t name;
720    
721      /* If the space is the receiver/owner of the object,
722         then we quietly consume the right and return
723         the space's name for the object.  Otherwise
724         we destroy the right and return RTMK_PORT_NULL.  */
725      switch (msgt_name)
726        {
727        case RTMK_MSG_TYPE_COPY_SEND:
728        case RTMK_MSG_TYPE_MOVE_SEND:
729        case RTMK_MSG_TYPE_MAKE_SEND:
730          {
731            thread_lock_write (&port->lock);
732            assert (port->srights > 0);
733            --port->srights;
734    
735            if (port->rcvobject == object)
736              name = port->rcvname;
737            else
738              name = RTMK_PORT_NULL;
739            thread_lock_unlock (&port->lock);
740            break;
741          }
742    
743    /* Set valid bit and right for port.  */      case RTMK_MSG_TYPE_MAKE_SEND_ONCE:
744    entry->ie_bits = IE_BITS_VALID | right;      case RTMK_MSG_TYPE_MOVE_SEND_ONCE:
745          {
746            thread_lock_write (&port->lock);
747            assert (port->sorights > 0);
748    
749            if (port->rcvobject == object)
750              {
751                /* quietly consume the send-once right */
752                port->sorights--;
753                name = port->rcvname;
754                thread_lock_unlock (&port->lock);
755              }
756            else
757              {
758                /* A very bizarre case.  The message
759                   was received, but before this copyout
760                   happened the space lost receive rights.
761                   We can't quietly consume the soright
762                   out from underneath some other task,
763                   so generate a send-once notification.  */
764                port->ref_count++;
765                thread_lock_unlock (&port->lock);
766    
767                name = RTMK_PORT_NULL;
768              }
769            break;
770          }
771          
772        default:
773          panic ("ipc_object_copyout_dest: strange rights");
774        }
775    
776    /* If SONCE is false, then we can insert it into the revese lookup    *namep = name;
      hash table aswell.  */        
   if (sonce == false)  
     ipc_reverse_insert (object, entry);  
     
777    return KERN_SUCCESS;    return KERN_SUCCESS;
778  }  }
779    
780  /* Remove NAME for OBJECT.  Return IPC entry in *ENTRYP.  */  /* Copyin a naked capability, PORT, from the kernel.  
781       PORT is the capability.  MSGT_NAME is transit type.  */
782  kern_return_t  kern_return_t
783  ipc_object_remove (struct ipc_object *object,  ipc_object_copyin_from_kernel (struct ipc_port *port,
784                     struct ipc_entry **entryp, rtmk_port_t name)                                 int msgt_name)
785  {  {
786    kern_return_t kr;    switch (msgt_name)
787          {
788    kr = ipc_object_lookup (object, name, entryp);      /* Transfering a receive right from the kernel.
789    if (kr != KERN_SUCCESS)         The receive object must be the kernel. */
790      return kr;      case RTMK_MSG_TYPE_MOVE_RECEIVE:
791    remove_entry (object, *entryp);        {
792            thread_lock_write (&port->lock);
793            assert (port->rcvobject == IPC_OBJECT_KERNEL ());
794            port->rcvobject = 0;
795            port->rcvname = RTMK_PORT_NULL;
796            port->msrights = 0;
797            thread_lock_unlock (&port->lock);
798            break;
799          }
800    
801        /* Copy a send right from the kernel to a user
802           IPC object.  We just increase the send right count.  */
803        case RTMK_MSG_TYPE_COPY_SEND:
804          {
805            thread_lock_write (&port->lock);
806            port->ref_count++;
807            port->srights++;
808            thread_lock_unlock (&port->lock);
809            break;
810          }
811    
812        /* Make a send right in a user IPC object.  The
813           kernel should hold the receive right.  */
814        case RTMK_MSG_TYPE_MAKE_SEND:
815          {
816            thread_lock_write (&port->lock);
817            assert (port->rcvobject == IPC_OBJECT_KERNEL ());
818            port->ref_count++;
819            port->srights++;
820            port->msrights++;
821            thread_lock_unlock (&port->lock);
822            break;
823          }
824    
825        /* Move send right into user IPC object.  */
826        case RTMK_MSG_TYPE_MOVE_SEND:
827          break;
828    
829        /* Move send-once right into user IPC object.  */
830        case RTMK_MSG_TYPE_MOVE_SEND_ONCE:
831          break;
832    
833        /* Make a send-once right user IPC object.  */
834        case RTMK_MSG_TYPE_MAKE_SEND_ONCE:
835          {
836            thread_lock_write (&port->lock);
837            assert (port->rcvobject == IPC_OBJECT_KERNEL ());
838            port->ref_count++;
839            port->sorights++;
840            thread_lock_unlock (&port->lock);
841            break;
842          }
843        }
844    return KERN_SUCCESS;    return KERN_SUCCESS;
845  }  }

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10

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