aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ode-0.9/ode/src/stack.h
blob: 5afff41a12eaddc6ad41578aecf67720b948dd26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

/* this comes from the `reuse' library. copy any changes back to the source.

these stack allocation functions are a replacement for alloca(), except that
they allocate memory from a separate pool.

advantages over alloca():
  - consecutive allocations are guaranteed to be contiguous with increasing
    address.
  - functions can allocate stack memory that is returned to the caller,
    in other words pushing and popping stack frames is optional.

disadvantages compared to alloca():
  - less portable
  - slightly slower, although still orders of magnitude faster than malloc().
  - longjmp() and exceptions do not deallocate stack memory (but who cares?).

just like alloca():
  - using too much stack memory does not fail gracefully, it fails with a
    segfault.

*/


#ifndef _ODE_STACK_H_
#define _ODE_STACK_H_


#ifdef WIN32
#include "windows.h"
#endif


struct dStack {
  char *base;		// bottom of the stack
  int size;		// maximum size of the stack
  char *pointer;	// current top of the stack
  char *frame;		// linked list of stack frame ptrs
# ifdef WIN32		// stuff for windows:
  int pagesize;		//   - page size - this is ASSUMED to be a power of 2
  int committed;	//   - bytes committed in allocated region
#endif

  // initialize the stack. `max_size' is the maximum size that the stack can
  // reach. on unix and windows a `virtual' memory block of this size is
  // mapped into the address space but does not actually consume physical
  // memory until it is referenced - so it is safe to set this to a high value.

  void init (int max_size);


  // destroy the stack. this unmaps any virtual memory that was allocated.

  void destroy();


  // allocate `size' bytes from the stack and return a pointer to the allocated
  // memory. `size' must be >= 0. the returned pointer will be aligned to the
  // size of a long int.

  char * alloc (int size)
  {
    char *ret = pointer;
    pointer += ((size-1) | (sizeof(long int)-1) )+1;
#   ifdef WIN32
    // for windows we need to commit pages as they are required
    if ((pointer-base) > committed) {
      committed = ((pointer-base-1) | (pagesize-1))+1;	// round up to pgsize
      VirtualAlloc (base,committed,MEM_COMMIT,PAGE_READWRITE);
    }
#   endif
    return ret;
  }


  // return the address that will be returned by the next call to alloc()

  char *nextAlloc()
  {
    return pointer;
  }


  // push and pop the current size of the stack. pushFrame() saves the current
  // frame pointer on the stack, and popFrame() retrieves it. a typical
  // stack-using function will bracket alloc() calls with pushFrame() and
  // popFrame(). both functions return the current stack pointer - this should
  // be the same value for the two bracketing calls. calling popFrame() too
  // many times will result in a segfault.

  char * pushFrame()
  {
    char *newframe = pointer;
    char **addr = (char**) alloc (sizeof(char*));
    *addr = frame;
    frame = newframe;
    return newframe;

    /* OLD CODE
	*((char**)pointer) = frame;
	frame = pointer;
	char *ret = pointer;
	pointer += sizeof(char*);
	return ret;
    */
  }

  char * popFrame()
  {
    pointer = frame;
    frame = *((char**)pointer);
    return pointer;
  }
};


#endif