Print this page
OS-4112 stack overflow from promisc callbacks
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/disp/thread_intr.c
          +++ new/usr/src/uts/common/disp/thread_intr.c
↓ open down ↓ 15 lines elided ↑ open up ↑
  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 2006 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26      -
  27   26  /*
  28      - * FILE NOTICE BEGIN
  29      - *
  30      - * This file should not be modified.  If you wish to modify it or have it
  31      - * modified, please contact Sun Microsystems at <LFI149367@-sun-.-com->
  32      - * (without anti-spam dashes)
  33      - *
  34      - * FILE NOTICE END
       27 + * Copyright 2015, Joyent, Inc.
  35   28   */
  36   29  
  37      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  38      -
  39   30  #include <sys/cpuvar.h>
  40   31  #include <sys/stack.h>
  41   32  #include <vm/seg_kp.h>
  42   33  #include <sys/proc.h>
  43   34  #include <sys/pset.h>
  44   35  #include <sys/sysmacros.h>
  45   36  
  46   37  /*
       38 + * Use a slightly larger thread stack size for interrupt threads rather than the
       39 + * default. This is useful for cases where the networking stack may do an rx and
       40 + * a tx in the context of a single interrupt and when combined with various
       41 + * promisc hooks that need memory, can cause us to get dangerously close to the
       42 + * edge of the traditional stack sizes. This is only a few pages more than a
       43 + * traditional stack and given that we don't have that many interrupt threads,
       44 + * the memory costs end up being more than worthwhile.
       45 + */
       46 +#define LL_INTR_STKSZ   (32 * 1024)
       47 +
       48 +/*
  47   49   * Create and initialize an interrupt thread.
  48   50   */
  49   51  static void
  50   52  thread_create_intr(cpu_t *cp)
  51   53  {
  52   54          kthread_t *tp;
  53   55  
  54      -        tp = thread_create(NULL, 0,
       56 +        tp = thread_create(NULL, LL_INTR_STKSZ,
  55   57              (void (*)())thread_create_intr, NULL, 0, &p0, TS_ONPROC, 0);
  56   58  
  57   59          /*
  58   60           * Set the thread in the TS_FREE state.  The state will change
  59   61           * to TS_ONPROC only while the interrupt is active.  Think of these
  60   62           * as being on a private free list for the CPU.  Being TS_FREE keeps
  61   63           * inactive interrupt threads out of debugger thread lists.
  62   64           *
  63   65           * We cannot call thread_create with TS_FREE because of the current
  64   66           * checks there for ONPROC.  Fix this when thread_create takes flags.
↓ open down ↓ 25 lines elided ↑ open up ↑
  90   92  #endif
  91   93  
  92   94          /*
  93   95           * Link onto CPU's interrupt pool.
  94   96           */
  95   97          tp->t_link = cp->cpu_intr_thread;
  96   98          cp->cpu_intr_thread = tp;
  97   99  }
  98  100  
  99  101  /*
 100      - * Allocate a given number of interrupt threads for a given CPU.
 101      - * These threads will get freed by cpu_destroy_bound_threads()
 102      - * when CPU gets unconfigured.
      102 + * Allocate a given number of interrupt threads for a given CPU.  These threads
      103 + * will get freed by cpu_destroy_bound_threads() when CPU gets unconfigured.
      104 + *
      105 + * Note, high level interrupts are always serviced using cpu_intr_stack and are
      106 + * not allowed to block. Low level interrupts or soft-interrupts use the
      107 + * kthread_t's that we create through the calls to thread_create_intr().
 103  108   */
 104  109  void
 105  110  cpu_intr_alloc(cpu_t *cp, int n)
 106  111  {
 107  112          int i;
 108  113  
 109  114          for (i = 0; i < n; i++)
 110  115                  thread_create_intr(cp);
 111  116  
 112  117          cp->cpu_intr_stack = (caddr_t)segkp_get(segkp, INTR_STACK_SIZE,
 113      -                KPD_HASREDZONE | KPD_NO_ANON | KPD_LOCKED) +
 114      -                INTR_STACK_SIZE - SA(MINFRAME);
      118 +            KPD_HASREDZONE | KPD_NO_ANON | KPD_LOCKED) +
      119 +            INTR_STACK_SIZE - SA(MINFRAME);
 115  120  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX