Print this page
OS-1988 Make ldi_ev_remove_callbacks safe to use in LDI callbacks

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/sys/sunldi_impl.h
          +++ new/usr/src/uts/common/sys/sunldi_impl.h
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
       25 +/*
       26 + * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
       27 + */
  25   28  
  26   29  #ifndef _SYS_SUNLDI_IMPL_H
  27   30  #define _SYS_SUNLDI_IMPL_H
  28   31  
  29      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  30      -
  31   32  #ifdef __cplusplus
  32   33  extern "C" {
  33   34  #endif
  34   35  
  35   36  #include <sys/dditypes.h>
  36   37  #include <sys/vnode.h>
  37   38  
  38   39  /*
  39   40   * NOTE
  40   41   *
↓ open down ↓ 93 lines elided ↑ open up ↑
 134  135          dev_t                   lec_dev;
 135  136          int                     lec_spec;
 136  137          int                     (*lec_notify)();
 137  138          void                    (*lec_finalize)();
 138  139          void                    *lec_arg;
 139  140          void                    *lec_cookie;
 140  141          void                    *lec_id;
 141  142          list_node_t             lec_list;
 142  143  } ldi_ev_callback_impl_t;
 143  144  
      145 +/*
      146 + * Members of "struct ldi_ev_callback_list" are protected by their le_lock
      147 + * member.  The struct is currently only used once, as a file-level global,
      148 + * and the locking protocol is currently implemented in ldi_ev_lock() and
      149 + * ldi_ev_unlock().
      150 + *
      151 + * When delivering events to subscribers, ldi_invoke_notify() and
      152 + * ldi_invoke_finalize() will walk the list of callbacks: le_head.  It is
      153 + * possible that an invoked callback function will need to unregister an
      154 + * arbitrary number of callbacks from this list.
      155 + *
      156 + * To enable ldi_ev_remove_callbacks() to remove elements from the list
      157 + * without breaking the walk-in-progress, we store the next element in the
      158 + * walk direction on the struct as le_walker_next and le_walker_prev.
      159 + */
 144  160  struct ldi_ev_callback_list {
 145      -        kmutex_t        le_lock;
 146      -        kcondvar_t      le_cv;
 147      -        int             le_busy;
 148      -        void            *le_thread;
 149      -        list_t          le_head;
      161 +        kmutex_t                le_lock;
      162 +        kcondvar_t              le_cv;
      163 +        int                     le_busy;
      164 +        void                    *le_thread;
      165 +        list_t                  le_head;
      166 +        ldi_ev_callback_impl_t  *le_walker_next;
      167 +        ldi_ev_callback_impl_t  *le_walker_prev;
 150  168  };
 151  169  
 152  170  int ldi_invoke_notify(dev_info_t *dip, dev_t dev, int spec_type, char *event,
 153  171      void *ev_data);
 154  172  void ldi_invoke_finalize(dev_info_t *dip, dev_t dev, int spec_type, char *event,
 155  173      int ldi_result, void *ev_data);
 156  174  int e_ddi_offline_notify(dev_info_t *dip);
 157  175  void e_ddi_offline_finalize(dev_info_t *dip, int result);
 158  176  
 159  177  
↓ open down ↓ 47 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX