Print this page
    
NEX-9981 Deadman timer panic from idm_refcnt_wait_ref thread while offlining iSCSI targets
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-6018 Return of the walking dead idm_refcnt_wait_ref comstar threads
Reviewed by:  Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by:  Evan Layton <evan.layton@nexenta.com>
NEX-3177 enums and string arrays required to be in sync.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/sys/idm/idm.h
          +++ new/usr/src/uts/common/sys/idm/idm.h
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  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  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
       24 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24   25   * Use is subject to license terms.
  25   26   */
  26   27  
  27   28  #ifndef _IDM_H
  28   29  #define _IDM_H
  29   30  
  30   31  #ifdef  __cplusplus
  31   32  extern "C" {
  32   33  #endif
  33   34  
       35 +#include <sys/stmf_defines.h>
       36 +
  34   37  typedef enum {
  35   38          IDM_STATUS_SUCCESS = 0,
  36   39          IDM_STATUS_FAIL,
  37   40          IDM_STATUS_NORESOURCES,
  38   41          IDM_STATUS_REJECT,
  39   42          IDM_STATUS_IO,
  40   43          IDM_STATUS_ABORTED,
  41   44          IDM_STATUS_SUSPENDED,
  42   45          IDM_STATUS_HEADER_DIGEST,
  43   46          IDM_STATUS_DATA_DIGEST,
  44   47          IDM_STATUS_PROTOCOL_ERROR,
  45   48          IDM_STATUS_LOGIN_FAIL
  46   49  } idm_status_t;
  47   50  
       51 +#define IDM_CLIENT_NOTIFY_LIST() \
       52 +        item(CN_UNDEFINED) \
       53 +        item(CN_CONNECT_ACCEPT)         /* Target only */ \
       54 +        item(CN_LOGIN_FAIL) \
       55 +        item(CN_READY_FOR_LOGIN)        /* Initiator only */ \
       56 +        item(CN_FFP_ENABLED) \
       57 +        item(CN_FFP_DISABLED) \
       58 +        item(CN_CONNECT_LOST) \
       59 +        item(CN_CONNECT_DESTROY) \
       60 +        item(CN_CONNECT_FAIL) \
       61 +        item(CN_MAX)
  48   62  
  49   63  typedef enum {
  50      -        CN_CONNECT_ACCEPT = 1,  /* Target only */
  51      -        CN_LOGIN_FAIL,
  52      -        CN_READY_FOR_LOGIN,     /* Initiator only */
  53      -        CN_FFP_ENABLED,
  54      -        CN_FFP_DISABLED,
  55      -        CN_CONNECT_LOST,
  56      -        CN_CONNECT_DESTROY,
  57      -        CN_CONNECT_FAIL,
  58      -        CN_MAX
       64 +#define item(a) a,
       65 +        IDM_CLIENT_NOTIFY_LIST()
       66 +#undef  item
  59   67  } idm_client_notify_t;
  60   68  
  61   69  #ifdef IDM_CN_NOTIFY_STRINGS
  62   70  static const char *idm_cn_strings[CN_MAX + 1] = {
  63      -        "CN_UNDEFINED",
  64      -        "CN_CONNECT_ACCEPT",
  65      -        "CN_LOGIN_FAIL",
  66      -        "CN_READY_FOR_LOGIN",
  67      -        "CN_FFP_ENABLED",
  68      -        "CN_FFP_DISABLED",
  69      -        "CN_CONNECT_LOST",
  70      -        "CN_CONNECT_DESTROY",
  71      -        "CN_CONNECT_FAIL",
  72      -        "CN_MAX"
       71 +#define item(a) #a,
       72 +        IDM_CLIENT_NOTIFY_LIST()
       73 +#undef  item
  73   74  };
  74   75  #endif
  75   76  
  76   77  typedef enum {
  77   78          FD_CONN_FAIL,
  78   79          FD_CONN_LOGOUT,
  79   80          FD_SESS_LOGOUT
  80   81  } idm_ffp_disable_t;
  81   82  
  82   83  typedef enum {
  83   84          AT_INTERNAL_SUSPEND,
  84   85          AT_INTERNAL_ABORT,
  85   86          AT_TASK_MGMT_ABORT
  86   87  } idm_abort_type_t;
  87   88  
       89 +#define IDM_TASK_STATE_LIST() \
       90 +        item(TASK_IDLE) \
       91 +        item(TASK_ACTIVE) \
       92 +        item(TASK_SUSPENDING) \
       93 +        item(TASK_SUSPENDED) \
       94 +        item(TASK_ABORTING) \
       95 +        item(TASK_ABORTED) \
       96 +        item(TASK_COMPLETE) \
       97 +        item(TASK_MAX_STATE)
       98 +
  88   99  typedef enum {
  89      -        TASK_IDLE,
  90      -        TASK_ACTIVE,
  91      -        TASK_SUSPENDING,
  92      -        TASK_SUSPENDED,
  93      -        TASK_ABORTING,
  94      -        TASK_ABORTED,
  95      -        TASK_COMPLETE,
  96      -        TASK_MAX_STATE
      100 +#define item(a) a,
      101 +        IDM_TASK_STATE_LIST()
      102 +#undef  item
  97  103  } idm_task_state_t;
  98  104  
  99  105  #ifdef IDM_TASK_SM_STRINGS
 100  106  static const char *idm_ts_name[TASK_MAX_STATE+1] = {
 101      -        "TASK_IDLE",
 102      -        "TASK_ACTIVE",
 103      -        "TASK_SUSPENDING",
 104      -        "TASK_SUSPENDED",
 105      -        "TASK_ABORTING",
 106      -        "TASK_ABORTED",
 107      -        "TASK_COMPLETE",
 108      -        "TASK_MAX_STATE"
      107 +#define item(a) #a,
      108 +        IDM_TASK_STATE_LIST()
      109 +#undef  item
 109  110  };
 110  111  #endif
 111  112  
 112  113  typedef enum {
 113  114          KV_HANDLED = 0,
 114  115          KV_HANDLED_NO_TRANSIT,
 115  116          KV_UNHANDLED,
 116  117          KV_TARGET_ONLY,
 117  118          KV_NO_RESOURCES,
 118  119          KV_INTERNAL_ERROR,
 119  120          KV_VALUE_ERROR,
 120  121          KV_MISSING_FIELDS,
 121  122          KV_AUTH_FAILED
 122  123  } kv_status_t;
 123  124  
 124  125  /*
 125  126   * Request structures
 126  127   */
 127  128  
 128  129  /* Defined in idm_impl.h */
 129  130  struct idm_conn_s;
 130  131  struct idm_svc_s;
 131  132  struct idm_buf_s;
 132  133  struct idm_pdu_s;
 133  134  struct idm_task_s;
 134  135  
 135  136  typedef idm_status_t (idm_client_notify_cb_t)(
 136  137      struct idm_conn_s *ic, idm_client_notify_t cn, uintptr_t data);
 137  138  
 138  139  typedef void (idm_rx_pdu_cb_t)(struct idm_conn_s *ic, struct idm_pdu_s *pdu);
 139  140  
 140  141  typedef void (idm_rx_pdu_error_cb_t)(struct idm_conn_s *ic,
 141  142      struct idm_pdu_s *pdu, idm_status_t status);
 142  143  
 143  144  typedef void (idm_buf_cb_t)(struct idm_buf_s *idb, idm_status_t status);
 144  145  
 145  146  typedef void (idm_pdu_cb_t)(struct idm_pdu_s *pdu, idm_status_t status);
 146  147  
 147  148  typedef void (idm_task_cb_t)(struct idm_task_s *task, idm_status_t status);
 148  149  
 149  150  typedef void (idm_build_hdr_cb_t)(
 150  151      struct idm_task_s *task, struct idm_pdu_s *pdu, uint8_t opcode);
 151  152  
 152  153  typedef void (idm_update_statsn_cb_t)(
 153  154      struct idm_task_s *task, struct idm_pdu_s *pdu);
 154  155  
 155  156  typedef void (idm_keepalive_cb_t)(struct idm_conn_s *ic);
 156  157  
 157  158  typedef union idm_sockaddr {
 158  159          struct sockaddr         sin;
 159  160          struct sockaddr_in      sin4;
 160  161          struct sockaddr_in6     sin6;
 161  162  } idm_sockaddr_t;
 162  163  
 163  164  #define SIZEOF_SOCKADDR(so)             \
 164  165          ((so)->sa_family == AF_INET ?   \
 165  166          sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6))
 166  167  
 167  168  typedef struct {
 168  169          idm_rx_pdu_cb_t         *icb_rx_scsi_cmd;
 169  170          idm_rx_pdu_cb_t         *icb_rx_scsi_rsp;
 170  171          idm_rx_pdu_cb_t         *icb_rx_misc;
 171  172          idm_rx_pdu_error_cb_t   *icb_rx_error;
 172  173          idm_task_cb_t           *icb_task_aborted;
 173  174          idm_client_notify_cb_t  *icb_client_notify;
 174  175          idm_build_hdr_cb_t      *icb_build_hdr;
 175  176          idm_update_statsn_cb_t  *icb_update_statsn; /* advance statsn */
 176  177          idm_keepalive_cb_t      *icb_keepalive;
 177  178  } idm_conn_ops_t;
 178  179  
 179  180  typedef struct {
 180  181          int                     cr_domain;
 181  182          int                     cr_type;
 182  183          int                     cr_protocol;
 183  184          boolean_t               cr_bound;
 184  185          idm_sockaddr_t          cr_bound_addr;
 185  186          idm_sockaddr_t          cr_ini_dst_addr;
 186  187          ldi_ident_t             cr_li;
 187  188          idm_conn_ops_t          icr_conn_ops;
 188  189          boolean_t               cr_boot_conn;
 189  190  } idm_conn_req_t;
 190  191  
 191  192  typedef struct {
 192  193          uint16_t                sr_port;
 193  194          ldi_ident_t             sr_li;
 194  195          idm_conn_ops_t          sr_conn_ops;
 195  196  } idm_svc_req_t;
 196  197  
 197  198  
 198  199  /* This is not how other networking code handles this */
 199  200  typedef struct {
 200  201          union {
 201  202                  struct in_addr  in4;
 202  203                  struct in6_addr in6;
 203  204          } i_addr;
 204  205          /* i_insize determines which is valid in the union above */
 205  206          int                     i_insize;
 206  207  } idm_ipaddr_t;
 207  208  
 208  209  typedef struct {
 209  210          idm_ipaddr_t            a_addr;
 210  211          uint32_t                a_port,
 211  212                                  a_oid;
 212  213  } idm_addr_t;
 213  214  
 214  215  typedef struct {
 215  216          uint32_t                al_vers,                        /* In */
 216  217                                  al_oid;                         /* In */
 217  218          uint32_t                al_in_cnt;                      /* In */
 218  219          uint32_t                al_out_cnt;                     /* Out */
 219  220          uint32_t                al_tpgt;                        /* Out */
 220  221          idm_addr_t              al_addrs[1];                    /* Out */
 221  222  } idm_addr_list_t;
 222  223  
 223  224  /*
 224  225   * State machine auditing
 225  226   */
 226  227  
 227  228  #define SM_AUDIT_BUF_MAX_REC    32
 228  229  
 229  230  typedef enum {
 230  231          SAR_UNDEFINED = 0,
 231  232          SAR_STATE_EVENT,
 232  233          SAR_STATE_CHANGE
 233  234  } sm_audit_record_type_t;
 234  235  
 235  236  typedef enum {
 236  237          SAS_UNDEFINED = 0,
 237  238          SAS_IDM_CONN,
 238  239          SAS_IDM_TASK,
 239  240          SAS_ISCSIT_TGT,
 240  241          SAS_ISCSIT_SESS,
 241  242          SAS_ISCSIT_LOGIN,
 242  243          SAS_ISCSI_CMD,
 243  244          SAS_ISCSI_SESS,
 244  245          SAS_ISCSI_CONN,
 245  246          SAS_ISCSI_LOGIN
 246  247  } sm_audit_sm_type_t;
 247  248  
 248  249  typedef struct {
 249  250          timespec_t              sar_timestamp;
 250  251          sm_audit_sm_type_t      sar_sm_type;
 251  252          sm_audit_record_type_t  sar_type;
 252  253          int                     sar_state;
 253  254          int                     sar_new_state;  /* Only for SAR_STATE_CHANGE */
 254  255          int                     sar_event;      /* Only for SAR_STATE_EVENT */
 255  256          uintptr_t               sar_event_info; /* Only for SAR_STATE_EVENT */
 256  257  } sm_audit_record_t;
 257  258  
 258  259  typedef struct {
 259  260          int                     sab_index;
 260  261          int                     sab_max_index;
 261  262          sm_audit_record_t       sab_records[SM_AUDIT_BUF_MAX_REC];
 262  263  } sm_audit_buf_t;
 263  264  
 264  265  extern boolean_t idm_sm_logging;
 265  266  extern boolean_t idm_conn_logging;
 266  267  extern boolean_t idm_svc_logging;
 267  268  
 268  269  #define IDM_SM_LOG if (idm_sm_logging) cmn_err
 269  270  #define IDM_CONN_LOG if (idm_conn_logging) cmn_err
 270  271  #define IDM_SVC_LOG if (idm_svc_logging) cmn_err
 271  272  
 272  273  void idm_sm_audit_init(sm_audit_buf_t *audit_buf);
 273  274  
 274  275  void idm_sm_audit_event(sm_audit_buf_t *audit_buf,
 275  276      sm_audit_sm_type_t sm_type,
 276  277      int state, int event, uintptr_t event_info);
 277  278  
 278  279  void idm_sm_audit_state_change(sm_audit_buf_t *audit_buf,
 279  280      sm_audit_sm_type_t sm_type, int state, int new_state);
 280  281  
 281  282  
 282  283  #include <sys/iscsi_protocol.h>
 283  284  #include <sys/idm/idm_conn_sm.h>
 284  285  #include <sys/idm/idm_transport.h>
 285  286  #include <sys/idm/idm_impl.h>
 286  287  #include <sys/idm/idm_text.h>
 287  288  #include <sys/idm/idm_so.h>
 288  289  
 289  290  /*
 290  291   * iSCSI Initiator Services
 291  292   */
 292  293  
 293  294  idm_status_t
 294  295  idm_ini_conn_create(idm_conn_req_t *cr, idm_conn_t **new_con);
 295  296  
 296  297  idm_status_t
 297  298  idm_ini_conn_connect(idm_conn_t *ic);
 298  299  
 299  300  void
 300  301  idm_ini_conn_disconnect(idm_conn_t *ic);
 301  302  
 302  303  void
 303  304  idm_ini_conn_disconnect_sync(idm_conn_t *ic);
 304  305  
 305  306  void
 306  307  idm_ini_conn_destroy(idm_conn_t *ic);
 307  308  
 308  309  /*
 309  310   * iSCSI Target Services
 310  311   */
 311  312  
 312  313  idm_status_t
 313  314  idm_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t **new_svc);
 314  315  
 315  316  idm_status_t
 316  317  idm_tgt_svc_online(idm_svc_t *is);
 317  318  
 318  319  void
 319  320  idm_tgt_svc_offline(idm_svc_t *is);
 320  321  
 321  322  void
 322  323  idm_tgt_svc_destroy(idm_svc_t *is);
 323  324  
 324  325  void
 325  326  idm_tgt_svc_destroy_if_unref(idm_svc_t *is);
 326  327  
 327  328  idm_svc_t *
 328  329  idm_tgt_svc_lookup(uint16_t port);
 329  330  
 330  331  void
 331  332  idm_tgt_svc_hold(idm_svc_t *is);
 332  333  
 333  334  void
 334  335  idm_tgt_svc_rele_and_destroy(idm_svc_t *is);
 335  336  
 336  337  idm_status_t
 337  338  idm_tgt_conn_accept(idm_conn_t *ic);
 338  339  
 339  340  void
 340  341  idm_tgt_conn_reject(idm_conn_t *ic);
 341  342  
 342  343  void
 343  344  idm_conn_hold(idm_conn_t *ic);
 344  345  
 345  346  void
 346  347  idm_conn_rele(idm_conn_t *ic);
 347  348  
 348  349  void
 349  350  idm_conn_set_target_name(idm_conn_t *ic, char *target_name);
 350  351  
 351  352  void
 352  353  idm_conn_set_initiator_name(idm_conn_t *ic, char *initiator_name);
 353  354  
 354  355  void
 355  356  idm_conn_set_isid(idm_conn_t *ic, uint8_t isid[ISCSI_ISID_LEN]);
 356  357  
 357  358  /*
 358  359   * Target data transfer services
 359  360   */
 360  361  idm_status_t
 361  362  idm_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb,
 362  363      uint32_t offset, uint32_t xfer_length,
 363  364      idm_buf_cb_t idb_buf_cb, void *cb_arg);
 364  365  
 365  366  idm_status_t
 366  367  idm_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb,
 367  368      uint32_t offset, uint32_t xfer_length,
 368  369      idm_buf_cb_t idb_buf_cb, void *cb_arg);
 369  370  
 370  371  void
 371  372  idm_buf_tx_to_ini_done(idm_task_t *idt, idm_buf_t *idb, idm_status_t status);
 372  373  
 373  374  void
 374  375  idm_buf_rx_from_ini_done(idm_task_t *idt, idm_buf_t *idb, idm_status_t status);
 375  376  
 376  377  #define XFER_BUF_TX_TO_INI      0
 377  378  #define XFER_BUF_RX_FROM_INI    1
 378  379  /*
 379  380   * Shared Initiator/Target Services
 380  381   */
 381  382  kv_status_t
 382  383  idm_negotiate_key_values(idm_conn_t *ic, nvlist_t *request_nvl,
 383  384      nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
 384  385  
 385  386  void
 386  387  idm_notice_key_values(idm_conn_t *ic, nvlist_t *negotiated_nvl);
 387  388  
 388  389  kv_status_t
 389  390  idm_declare_key_values(idm_conn_t *ic, nvlist_t *config_nvl,
 390  391      nvlist_t *outgoing_nvl);
 391  392  
 392  393  /*
 393  394   * Buffer services
 394  395   */
 395  396  
 396  397  idm_buf_t *
 397  398  idm_buf_alloc(idm_conn_t *ic, void *bufptr, uint64_t buflen);
 398  399  
 399  400  void
 400  401  idm_buf_free(idm_buf_t *idb);
 401  402  
 402  403  void
 403  404  idm_buf_bind_in(idm_task_t *idt, idm_buf_t *buf);
 404  405  
 405  406  void
 406  407  idm_buf_bind_out(idm_task_t *idt, idm_buf_t *buf);
 407  408  
 408  409  void
 409  410  idm_buf_unbind_in(idm_task_t *idt, idm_buf_t *buf);
 410  411  
 411  412  void
 412  413  idm_buf_unbind_out(idm_task_t *idt, idm_buf_t *buf);
 413  414  
 414  415  idm_buf_t *
 415  416  idm_buf_find(void *lbuf, size_t data_offset);
 416  417  
 417  418  void
 418  419  idm_bufpat_set(idm_buf_t *idb);
 419  420  
 420  421  boolean_t
 421  422  idm_bufpat_check(idm_buf_t *idb, int check_len, idm_bufpat_check_type_t type);
 422  423  
 423  424  extern boolean_t idm_pattern_checking;
 424  425  
 425  426  #define IDM_BUFPAT_SET(CHK_BUF)                                 \
 426  427          if (idm_pattern_checking && (CHK_BUF)->idb_bufalloc) {  \
 427  428                  idm_bufpat_set(CHK_BUF);                        \
 428  429          }
 429  430  
 430  431  #define IDM_BUFPAT_CHECK(CHK_BUF, CHK_LEN, CHK_TYPE)            \
 431  432          if (idm_pattern_checking) {                             \
 432  433                  (void) idm_bufpat_check(CHK_BUF, CHK_LEN, CHK_TYPE);    \
 433  434          }
  
    | 
      ↓ open down ↓ | 
    315 lines elided | 
    
      ↑ open up ↑ | 
  
 434  435  
 435  436  /*
 436  437   * Task services
 437  438   */
 438  439  idm_task_t *
 439  440  idm_task_alloc(idm_conn_t *ic);
 440  441  
 441  442  void
 442  443  idm_task_start(idm_task_t *idt, uintptr_t handle);
 443  444  
 444      -void
      445 +stmf_status_t
 445  446  idm_task_abort(idm_conn_t *ic, idm_task_t *idt, idm_abort_type_t abort_type);
 446  447  
 447  448  void
 448  449  idm_task_cleanup(idm_task_t *idt);
 449  450  
 450  451  void
 451  452  idm_task_done(idm_task_t *idt);
 452  453  
 453  454  void
 454  455  idm_task_free(idm_task_t *idt);
 455  456  
 456  457  idm_task_t *
 457  458  idm_task_find(idm_conn_t *ic, uint32_t itt, uint32_t ttt);
 458  459  
 459  460  idm_task_t *
 460  461  idm_task_find_and_complete(idm_conn_t *ic, uint32_t itt, uint32_t ttt);
 461  462  
 462  463  void *
 463  464  idm_task_find_by_handle(idm_conn_t *ic, uintptr_t handle);
 464  465  
 465  466  void
 466  467  idm_task_hold(idm_task_t *idt);
 467  468  
 468  469  void
 469  470  idm_task_rele(idm_task_t *idt);
 470  471  
 471  472  /*
 472  473   * PDU Services
 473  474   */
 474  475  
 475  476  idm_pdu_t *
 476  477  idm_pdu_alloc(uint_t hdrlen, uint_t datalen);
 477  478  
 478  479  idm_pdu_t *
 479  480  idm_pdu_alloc_nosleep(uint_t hdrlen, uint_t datalen);
 480  481  
 481  482  void
 482  483  idm_pdu_free(idm_pdu_t *pdu);
 483  484  
 484  485  void
 485  486  idm_pdu_init(idm_pdu_t *pdu, idm_conn_t *ic, void *private, idm_pdu_cb_t *cb);
 486  487  
 487  488  void
 488  489  idm_pdu_init_hdr(idm_pdu_t *pdu, uint8_t *hdr, uint_t hdrlen);
 489  490  
 490  491  void
 491  492  idm_pdu_init_data(idm_pdu_t *pdu, uint8_t *data, uint_t datalen);
 492  493  
 493  494  void
 494  495  idm_pdu_complete(idm_pdu_t *pdu, idm_status_t status);
 495  496  
 496  497  void
 497  498  idm_pdu_tx(idm_pdu_t *pdu);
 498  499  
 499  500  /*
 500  501   * Object reference tracking
 501  502   */
 502  503  
 503  504  void
 504  505  idm_refcnt_init(idm_refcnt_t *refcnt, void *referenced_obj);
 505  506  
 506  507  void
 507  508  idm_refcnt_destroy(idm_refcnt_t *refcnt);
 508  509  
 509  510  void
 510  511  idm_refcnt_reset(idm_refcnt_t *refcnt);
 511  512  
 512  513  void
 513  514  idm_refcnt_hold(idm_refcnt_t *refcnt);
 514  515  
 515  516  void
 516  517  idm_refcnt_rele(idm_refcnt_t *refcnt);
  
    | 
      ↓ open down ↓ | 
    62 lines elided | 
    
      ↑ open up ↑ | 
  
 517  518  
 518  519  void
 519  520  idm_refcnt_rele_and_destroy(idm_refcnt_t *refcnt, idm_refcnt_cb_t *cb_func);
 520  521  
 521  522  void
 522  523  idm_refcnt_wait_ref(idm_refcnt_t *refcnt);
 523  524  
 524  525  void
 525  526  idm_refcnt_async_wait_ref(idm_refcnt_t *refcnt, idm_refcnt_cb_t *cb_func);
 526  527  
      528 +int
      529 +idm_refcnt_is_held(idm_refcnt_t *refcnt);
 527  530  
 528  531  #ifdef  __cplusplus
 529  532  }
 530  533  #endif
 531  534  
 532  535  #endif /* _IDM_H */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX