aboutsummaryrefslogtreecommitdiff
path: root/sys/nmemio/salloc.x
blob: 34f06217ca94e6d935d6baf93a3610a2145f2b96 (plain) (blame)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<config.h>
include	<syserr.h>

# SALLOC.X -- Stack management routines.  Stack storage is allocated in
# segments.  Space for each segment is dynamically allocated on the heap.
# Each segment contains a pointer to the previous segment to permit
# reclamation of the space (see "Mem.hlp" for additional details).
# This is a low level facility, hence any failure to allocate or deallocate
# stack storage is fatal.


# Segment header structure.  The header size parameter SZ_STKHDR is defined
# in <config.h> because it is potentially machine dependent.  SZ_STKHDR
# must be chosen such that the maximum alignment criteria is maintained.

define	SH_BASE		Memi[$1]	# char pointer to base of segment
define	SH_TOP		Memi[$1+1]	# char pointer to top of segment + 1
define	SH_OLDSEG	Memi[$1+2]	# struct pointer to header of prev.seg.


# SALLOC -- Allocate space on the stack.

procedure salloc (output_pointer, nelem, datatype)

pointer	output_pointer		# buffer pointer (output)
int	nelem			# number of elements of storage required
int	datatype		# datatype of the storage elements

int	nchars, dtype
include	<szdtype.inc>
pointer	sp, cur_seg
common	/salcom/ sp, cur_seg

begin
	dtype = datatype
	if (dtype < 1 || dtype > MAX_DTYPE)
	    call sys_panic (500, "salloc: bad datatype code")

	# Align stack pointer for any data type.  Compute amount of
	# storage to be allocated.  Always add space for at least one
	# extra char for the EOS in case a string is stored in the buffer.

	sp = (sp + SZ_MEMALIGN-1) / SZ_MEMALIGN * SZ_MEMALIGN + 1
	if (dtype == TY_CHAR)
	    nchars = nelem + 1				# add space for EOS
	else
	    nchars = nelem * ty_size[dtype] + 1

	# Check for stack overflow, add new segment if out of room.
	# Since SMARK must be called before SALLOC, cur_seg cannot be
	# null, but we check anyhow.

	if (cur_seg == NULL || sp + nchars >= SH_TOP(cur_seg))
	    call stk_mkseg (cur_seg, sp, nchars)

	if (dtype == TY_CHAR)
	    output_pointer = sp
	else
	    output_pointer = (sp-1) / ty_size[dtype] + 1

	sp = sp + nchars			# bump stack pointer
end


# SMARK -- Mark the position of the stack pointer, so that stack space
# can be freed by a subsequent call to SFREE.  This routine also performs
# initialization of the stack, since it the very first routine called
# during task startup.

procedure smark (old_sp)

pointer	old_sp			# value of the stack pointer (output)
bool	first_time
pointer	sp, cur_seg
common	/salcom/ sp, cur_seg
data	first_time /true/

begin
	if (first_time) {
	    sp = NULL
	    cur_seg = NULL
	    call stk_mkseg (cur_seg, sp, SZ_STACK)
	    first_time = false
	}

	old_sp = sp
end


# SFREE -- Free space on the stack.  Return whole segments until segment
# containing the old stack pointer is reached.

procedure sfree (old_sp)

pointer	old_sp			# previous value of the stack pointer

pointer	old_seg
pointer	sp, cur_seg
common	/salcom/ sp, cur_seg

begin
	# The following is needed to avoid recursion when SFREE is called
	# by the IRAF main during processing of SYS_MSSTKUNFL.

	if (cur_seg == NULL)
	    return
	    
	# If the stack underflows (probably because of an invalid pointer)
	# it is a fatal error.

	while (old_sp < SH_BASE(cur_seg) || old_sp > SH_TOP(cur_seg)) {
	    if (SH_OLDSEG(cur_seg) == NULL)
		call sys_panic (SYS_MSSTKUNFL, "Salloc underflow")

	    old_seg = SH_OLDSEG(cur_seg)		# discard segment
	    call mfree (cur_seg, TY_STRUCT)
	    cur_seg = old_seg
	}

	sp = old_sp					# pop stack
end


# STK_MKSEG -- Create and add a new stack segment (link at head of the
# segment list).  Called during initialization, and upon stack overflow.

procedure stk_mkseg (cur_seg, sp, segment_size)

pointer	cur_seg			# current segment
pointer	sp			# salloc stack pointer
int	segment_size		# size of new stack segment

int	nchars, new_seg
pointer	coerce() 
int	kmalloc()

begin
	# Compute size of new segment, allocate the buffer.
	nchars = max (SZ_STACK, segment_size) + SZ_STKHDR
	if (kmalloc (new_seg, nchars / SZ_STRUCT, TY_STRUCT) == ERR)
	    call sys_panic (SYS_MFULL, "Out of memory")

	# Output new stack pointer.
	sp = coerce (new_seg, TY_STRUCT, TY_CHAR) + SZ_STKHDR

	# Set up the segment descriptor.
	SH_BASE(new_seg) = sp
	SH_TOP(new_seg) = sp - SZ_STKHDR + nchars
	SH_OLDSEG(new_seg) = cur_seg

	# Make new segment the current segment.
	cur_seg = new_seg
end