if (n->type == VLIB_NODE_TYPE_PROCESS)
{
vlib_process_t *p;
- uword log2_n_stack_bytes;
+ void *map;
+ uword log2_n_stack_bytes, stack_bytes;
+ int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
- log2_n_stack_bytes = clib_max (r->process_log2_n_stack_bytes, 15);
+ log2_n_stack_bytes = clib_max (r->process_log2_n_stack_bytes,
+ VLIB_PROCESS_LOG2_STACK_SIZE);
+ log2_n_stack_bytes = clib_max (log2_n_stack_bytes,
+ min_log2 (page_size));
-#ifdef CLIB_UNIX
- /*
- * Bump the stack size if running over a kernel with a large page size,
- * and the stack isn't any too big to begin with. Otherwise, we'll
- * trip over the stack guard page for sure.
- */
- if ((page_size > (4 << 10)) && log2_n_stack_bytes < 19)
- {
- if ((1 << log2_n_stack_bytes) <= page_size)
- log2_n_stack_bytes = min_log2 (page_size) + 1;
- else
- log2_n_stack_bytes++;
- }
-#endif
+ p = clib_mem_alloc_aligned (sizeof (p[0]), CLIB_CACHE_LINE_BYTES);
+ clib_memset (p, 0, sizeof (p[0]));
+ p->log2_n_stack_bytes = log2_n_stack_bytes;
- p = clib_mem_alloc_aligned_at_offset
- (sizeof (p[0]) + (1 << log2_n_stack_bytes),
- STACK_ALIGN, STRUCT_OFFSET_OF (vlib_process_t, stack),
- 0 /* no, don't call os_out_of_memory */ );
- if (p == 0)
+ stack_bytes = 1 << log2_n_stack_bytes;
+ /* map stack size + 2 extra guard pages */
+ map = mmap (0, stack_bytes + page_size, PROT_READ | PROT_WRITE,
+ mmap_flags, -1, 0);
+
+ if (map == MAP_FAILED)
clib_panic ("failed to allocate process stack (%d bytes)",
- 1 << log2_n_stack_bytes);
+ stack_bytes);
- clib_memset (p, 0, sizeof (p[0]));
- p->log2_n_stack_bytes = log2_n_stack_bytes;
+ /* skip the guard page */
+ p->stack = map + page_size;
+
+ mmap_flags |= MAP_FIXED;
+ map = mmap (map, page_size, PROT_NONE, mmap_flags, -1, 0);
+
+ if (map == MAP_FAILED)
+ clib_unix_warning ("failed to create stack guard page");
/* Process node's runtime index is really index into process
pointer vector. */
/* Node runtime is stored inside of process. */
rt = &p->node_runtime;
-
-#ifdef CLIB_UNIX
- /*
- * Disallow writes to the bottom page of the stack, to
- * catch stack overflows.
- */
- if (mprotect (p->stack, page_size, PROT_READ) < 0)
- clib_unix_warning ("process stack");
-#endif
-
}
else
{
typedef struct
{
+ CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
/* Node runtime for this process. */
vlib_node_runtime_t node_runtime;
vlib_cli_output_function_t *output_function;
uword output_function_arg;
-#ifdef CLIB_UNIX
- /* Pad to a multiple of the page size so we can mprotect process stacks */
-#define PAGE_SIZE_MULTIPLE 0x1000
-#define ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT __attribute__ ((aligned (PAGE_SIZE_MULTIPLE)))
-#else
-#define ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT
-#endif
-
- /* Process stack. Starts here and extends 2^log2_n_stack_bytes
- bytes. */
-
+ /* Process stack */
#define VLIB_PROCESS_STACK_MAGIC (0xdead7ead)
- u32 stack[0] ALIGN_ON_MULTIPLE_PAGE_BOUNDARY_FOR_MPROTECT;
-} vlib_process_t __attribute__ ((aligned (CLIB_CACHE_LINE_BYTES)));
-
-#ifdef CLIB_UNIX
- /* Ensure that the stack is aligned on the multiple of the page size */
-typedef char
- assert_process_stack_must_be_aligned_exactly_to_page_size_multiple[(sizeof
- (vlib_process_t)
- -
- PAGE_SIZE_MULTIPLE)
- ==
- 0 ? 0 :
- -1];
-#endif
+ u32 *stack;
+} vlib_process_t;
typedef struct
{