(scm_cell, scm_double_cell): Also allow USE_COPT_THREADS to not
[bpt/guile.git] / libguile / inline.h
1 /* classes: h_files */
2
3 #ifndef SCM_INLINE_H
4 #define SCM_INLINE_H
5
6 /* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this software; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21 * Boston, MA 02111-1307 USA
22 *
23 * As a special exception, the Free Software Foundation gives permission
24 * for additional uses of the text contained in its release of GUILE.
25 *
26 * The exception is that, if you link the GUILE library with other files
27 * to produce an executable, this does not by itself cause the
28 * resulting executable to be covered by the GNU General Public License.
29 * Your use of that executable is in no way restricted on account of
30 * linking the GUILE library code into it.
31 *
32 * This exception does not however invalidate any other reasons why
33 * the executable file might be covered by the GNU General Public License.
34 *
35 * This exception applies only to the code released by the
36 * Free Software Foundation under the name GUILE. If you copy
37 * code from other Free Software Foundation releases into a copy of
38 * GUILE, as the General Public License permits, the exception does
39 * not apply to the code that you add in this way. To avoid misleading
40 * anyone as to the status of such modified files, you must delete
41 * this exception notice from them.
42 *
43 * If you write modifications of your own for GUILE, it is your choice
44 * whether to permit this exception to apply to your modifications.
45 * If you do not wish that, delete this exception notice. */
46
47 /* This file is for inline functions. On platforms that don't support
48 inlining functions, they are turned into ordinary functions. See
49 "inline.c".
50 */
51
52
53 #if (SCM_DEBUG_CELL_ACCESSES == 1)
54 #include <stdio.h>
55
56 #endif
57
58 #include "libguile/pairs.h"
59 #include "libguile/gc.h"
60
61
62 SCM_API SCM scm_cell (scm_t_bits car, scm_t_bits cdr);
63 SCM_API SCM scm_double_cell (scm_t_bits car, scm_t_bits cbr,
64 scm_t_bits ccr, scm_t_bits cdr);
65
66 #ifdef HAVE_INLINE
67
68 #ifndef EXTERN_INLINE
69 #define EXTERN_INLINE extern inline
70 #endif
71
72 extern unsigned scm_newcell2_count;
73 extern unsigned scm_newcell_count;
74
75
76
77 EXTERN_INLINE
78 SCM
79 scm_cell (scm_t_bits car, scm_t_bits cdr)
80 {
81 SCM z;
82
83 if (SCM_NULLP (scm_i_freelist))
84 {
85 z = scm_gc_for_newcell (&scm_i_master_freelist, &scm_i_freelist);
86 }
87 else
88 {
89 z = scm_i_freelist;
90 scm_i_freelist = SCM_FREE_CELL_CDR (scm_i_freelist);
91 }
92
93 /*
94 We update scm_cells_allocated from this function. If we don't
95 update this explicitly, we will have to walk a freelist somewhere
96 later on, which seems a lot more expensive.
97 */
98 scm_cells_allocated += 1;
99
100 #if (SCM_DEBUG_CELL_ACCESSES == 1)
101 if (scm_debug_cell_accesses_p)
102 {
103 if (SCM_GC_MARK_P (z))
104 {
105 fprintf(stderr, "scm_cell tried to allocate a marked cell.\n");
106 abort();
107 }
108 else if (SCM_GC_CELL_TYPE(z) != scm_tc_free_cell)
109 {
110 fprintf(stderr, "cell from freelist is not a free cell.\n");
111 abort();
112 }
113 }
114
115 /*
116 Always set mark. Otherwise cells that are alloced before
117 scm_debug_cell_accesses_p is toggled seem invalid.
118 */
119 SCM_SET_GC_MARK (z);
120
121 /*
122 TODO: figure out if this use of mark bits is valid with
123 threading. What if another thread is doing GC at this point
124 ... ?
125 */
126
127 #endif
128
129
130 /* Initialize the type slot last so that the cell is ignored by the
131 GC until it is completely initialized. This is only relevant
132 when the GC can actually run during this code, which it can't for
133 cooperating threads, but it might be important when we get true
134 preemptive threads.
135 */
136 SCM_GC_SET_CELL_WORD (z, 1, cdr);
137 SCM_GC_SET_CELL_WORD (z, 0, car);
138
139 #ifdef USE_THREADS
140 #if !defined(USE_COOP_THREADS) && !defined(USE_NULL_THREADS) && !defined(USE_COPT_THREADS)
141 /* When we are using preemtive threads, we might need to make
142 sure that the initial values for the slots are protected until
143 the cell is completely initialized.
144 */
145 #error review me
146 scm_remember_upto_here_1 (SCM_PACK (cdr));
147 #endif
148 #endif
149
150
151 #if (SCM_DEBUG_CELL_ACCESSES == 1)
152 if (scm_expensive_debug_cell_accesses_p )
153 scm_i_expensive_validation_check (z);
154 #endif
155
156 return z;
157 }
158
159 EXTERN_INLINE
160 SCM
161 scm_double_cell (scm_t_bits car, scm_t_bits cbr,
162 scm_t_bits ccr, scm_t_bits cdr)
163 {
164 SCM z;
165
166
167 if (SCM_NULLP (scm_i_freelist2))
168 {
169 z = scm_gc_for_newcell (&scm_i_master_freelist2, &scm_i_freelist2);
170 }
171 else
172 {
173 z = scm_i_freelist2;
174 scm_i_freelist2 = SCM_FREE_CELL_CDR (scm_i_freelist2);
175 }
176
177 scm_cells_allocated += 2;
178
179 /* Initialize the type slot last so that the cell is ignored by the
180 GC until it is completely initialized. This is only relevant
181 when the GC can actually run during this code, which it can't for
182 cooperating threads, but it might be important when we get true
183 preemptive threads.
184 */
185 SCM_GC_SET_CELL_WORD (z, 1, cbr);
186 SCM_GC_SET_CELL_WORD (z, 2, ccr);
187 SCM_GC_SET_CELL_WORD (z, 3, cdr);
188 SCM_GC_SET_CELL_WORD (z, 0, car);
189
190 #ifdef USE_THREADS
191 #if !defined(USE_COOP_THREADS) && !defined(USE_NULL_THREADS) && !defined(USE_COPT_THREADS)
192 /* When we are using non-cooperating threads, we might need to make
193 sure that the initial values for the slots are protected until
194 the cell is completely initialized.
195 */
196 #error review me
197 scm_remember_upto_here_3 (SCM_PACK (cbr), SCM_PACK (ccr), SCM_PACK (cdr));
198 #endif
199 #endif
200
201
202 #if (SCM_DEBUG_CELL_ACCESSES == 1)
203 if (scm_debug_cell_accesses_p)
204 {
205 if (SCM_GC_MARK_P (z))
206 {
207 fprintf(stderr,
208 "scm_double_cell tried to allocate a marked cell.\n");
209 abort();
210 }
211 }
212
213 /* see above. */
214 SCM_SET_GC_MARK (z);
215
216 #endif
217
218 /* When this function is inlined, it's possible that the last
219 SCM_GC_SET_CELL_WORD above will be adjacent to a following
220 initialization of z. E.g., it occurred in scm_make_real. GCC
221 from around version 3 (e.g., certainly 3.2) began taking
222 advantage of strict C aliasing rules which say that it's OK to
223 interchange the initialization above and the one below when the
224 pointer types appear to differ sufficiently. We don't want that,
225 of course. GCC allows this behaviour to be disabled with the
226 -fno-strict-aliasing option, but would also need to be supplied
227 by Guile users. Instead, the following statements prevent the
228 reordering.
229 */
230 #ifdef __GNUC__
231 asm volatile ("" : : : "memory");
232 #else
233 /* portable version, just in case any other compiler does the same
234 thing. */
235 scm_remember_upto_here_1 (z);
236 #endif
237
238 return z;
239 }
240
241
242
243 #endif
244 #endif