~ubuntu-branches/ubuntu/karmic/luatex/karmic

« back to all changes in this revision

Viewing changes to src/libs/lua51/lcoco.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2007-12-10 10:24:34 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071210102434-9w9ljypghznwb4dy
Tags: 0.20.1-1
* new upstreams, add the announcements with changes to the debian dir
* call build.sh.linux with bash, not with sh, otherwise building breaks
  (thanks to Pascal de Bruijn <pmjdebruijn@gmail.com> from Ubuntu for
  letting us know) [np]
* update libpoppler patch
* change the texdoclua patch to use the new os.tmpdir with a template of
  /tmp/luatex.XXXXXX
* bump standards version to 3.7.3, no changes necessary
* convert copyright file to utf-8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** Copyright (C) 2004-2007 Mike Pall. All rights reserved.
 
3
**
 
4
** Permission is hereby granted, free of charge, to any person obtaining
 
5
** a copy of this software and associated documentation files (the
 
6
** "Software"), to deal in the Software without restriction, including
 
7
** without limitation the rights to use, copy, modify, merge, publish,
 
8
** distribute, sublicense, and/or sell copies of the Software, and to
 
9
** permit persons to whom the Software is furnished to do so, subject to
 
10
** the following conditions:
 
11
**
 
12
** The above copyright notice and this permission notice shall be
 
13
** included in all copies or substantial portions of the Software.
 
14
**
 
15
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
16
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 
19
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
20
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
21
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
22
**
 
23
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
 
24
*/
 
25
 
 
26
/* Coco -- True C coroutines for Lua. http://luajit.org/coco.html */
 
27
#ifndef COCO_DISABLE
 
28
 
 
29
#define lcoco_c
 
30
#define LUA_CORE
 
31
 
 
32
#include "lua.h"
 
33
 
 
34
#include "lobject.h"
 
35
#include "lstate.h"
 
36
#include "ldo.h"
 
37
#include "lvm.h"
 
38
#include "lgc.h"
 
39
 
 
40
 
 
41
/*
 
42
** Define this if you want to run Coco with valgrind. You will get random
 
43
** errors about accessing memory from newly allocated C stacks if you don't.
 
44
** You need at least valgrind 3.0 for this to work.
 
45
**
 
46
** This macro evaluates to a no-op if not run with valgrind. I.e. you can
 
47
** use the same binary for regular runs, too (without a performance loss).
 
48
*/
 
49
#ifdef USE_VALGRIND
 
50
#include <valgrind/valgrind.h>
 
51
#define STACK_REG(coco, p, sz)  (coco)->vgid = VALGRIND_STACK_REGISTER(p, p+sz);
 
52
#define STACK_DEREG(coco)       VALGRIND_STACK_DEREGISTER((coco)->vgid);
 
53
#define STACK_VGID              unsigned int vgid;
 
54
#else
 
55
#define STACK_REG(coco, p, sz)
 
56
#define STACK_DEREG(id)
 
57
#define STACK_VGID
 
58
#endif
 
59
 
 
60
/* ------------------------------------------------------------------------ */
 
61
 
 
62
/* Use Windows Fibers. */
 
63
#if defined(COCO_USE_FIBERS)
 
64
 
 
65
#define _WIN32_WINNT 0x0400
 
66
#include <windows.h>
 
67
 
 
68
#define COCO_MAIN_DECL          CALLBACK
 
69
 
 
70
typedef LPFIBER_START_ROUTINE coco_MainFunc;
 
71
 
 
72
#define COCO_NEW(OL, NL, cstacksize, mainfunc) \
 
73
  if ((L2COCO(NL)->fib = CreateFiber(cstacksize, mainfunc, NL)) == NULL) \
 
74
    luaD_throw(OL, LUA_ERRMEM);
 
75
 
 
76
#define COCO_FREE(L) \
 
77
  DeleteFiber(L2COCO(L)->fib); \
 
78
  L2COCO(L)->fib = NULL;
 
79
 
 
80
/* See: http://blogs.msdn.com/oldnewthing/archive/2004/12/31/344799.aspx */
 
81
#define COCO_JUMPIN(coco) \
 
82
  { void *cur = GetCurrentFiber(); \
 
83
    coco->back = (cur == NULL || cur == (void *)0x1e00) ? \
 
84
      ConvertThreadToFiber(NULL) : cur; } \
 
85
  SwitchToFiber(coco->fib);
 
86
 
 
87
#define COCO_JUMPOUT(coco) \
 
88
  SwitchToFiber(coco->back);
 
89
 
 
90
/* CreateFiber() defaults to STACKSIZE from the Windows module .def file. */
 
91
#define COCO_DEFAULT_CSTACKSIZE         0
 
92
 
 
93
/* ------------------------------------------------------------------------ */
 
94
 
 
95
#else /* !COCO_USE_FIBERS */
 
96
 
 
97
#ifndef COCO_USE_UCONTEXT
 
98
 
 
99
/* Try inline asm first. */
 
100
#if __GNUC__ >= 3 && !defined(COCO_USE_SETJMP)
 
101
 
 
102
#if defined(__i386) || defined(__i386__)
 
103
 
 
104
#ifdef __PIC__
 
105
typedef void *coco_ctx[4];  /* eip, esp, ebp, ebx */
 
106
static inline void coco_switch(coco_ctx from, coco_ctx to)
 
107
{
 
108
  __asm__ __volatile__ (
 
109
    "call 1f\n" "1:\tpopl %%eax\n\t" "addl $(2f-1b),%%eax\n\t"
 
110
    "movl %%eax, (%0)\n\t" "movl %%esp, 4(%0)\n\t"
 
111
    "movl %%ebp, 8(%0)\n\t" "movl %%ebx, 12(%0)\n\t"
 
112
    "movl 12(%1), %%ebx\n\t" "movl 8(%1), %%ebp\n\t"
 
113
    "movl 4(%1), %%esp\n\t" "jmp *(%1)\n" "2:\n"
 
114
    : "+S" (from), "+D" (to) : : "eax", "ecx", "edx", "memory", "cc");
 
115
}
 
116
#else
 
117
typedef void *coco_ctx[3];  /* eip, esp, ebp */
 
118
static inline void coco_switch(coco_ctx from, coco_ctx to)
 
119
{
 
120
  __asm__ __volatile__ (
 
121
    "movl $1f, (%0)\n\t" "movl %%esp, 4(%0)\n\t" "movl %%ebp, 8(%0)\n\t"
 
122
    "movl 8(%1), %%ebp\n\t" "movl 4(%1), %%esp\n\t" "jmp *(%1)\n" "1:\n"
 
123
    : "+S" (from), "+D" (to) : : "eax", "ebx", "ecx", "edx", "memory", "cc");
 
124
}
 
125
#endif
 
126
 
 
127
#define COCO_CTX                coco_ctx
 
128
#define COCO_SWITCH(from, to)   coco_switch(from, to);
 
129
#define COCO_MAKECTX(coco, buf, func, stack, a0) \
 
130
  buf[0] = (void *)(func); \
 
131
  buf[1] = (void *)(stack); \
 
132
  buf[2] = (void *)0; \
 
133
  stack[0] = 0xdeadc0c0;  /* Dummy return address. */ \
 
134
  coco->arg0 = (size_t)(a0);
 
135
#define COCO_STATE_HEAD         size_t arg0;
 
136
 
 
137
#elif __mips && _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi)
 
138
 
 
139
/* No way to avoid the function prologue with inline assembler. So use this: */
 
140
static const unsigned int coco_switch[] = {
 
141
#ifdef __mips_soft_float
 
142
#define COCO_STACKSAVE          -10
 
143
  0x27bdffd8,  /* addiu sp, sp, -(10*4) */
 
144
#else
 
145
#define COCO_STACKSAVE          -22
 
146
  0x27bdffa8,  /* addiu sp, sp, -(10*4+6*8) */
 
147
  /* sdc1 {$f20-$f30}, offset(sp) */
 
148
  0xf7be0050, 0xf7bc0048, 0xf7ba0040, 0xf7b80038, 0xf7b60030, 0xf7b40028,
 
149
#endif
 
150
  /* sw {gp,s0-s8}, offset(sp) */
 
151
  0xafbe0024, 0xafb70020, 0xafb6001c, 0xafb50018, 0xafb40014, 0xafb30010,
 
152
  0xafb2000c, 0xafb10008, 0xafb00004, 0xafbc0000,
 
153
  /* sw sp, 4(a0); sw ra, 0(a0); lw ra, 0(a1); lw sp, 4(a1); move t9, ra */
 
154
  0xac9d0004, 0xac9f0000, 0x8cbf0000, 0x8cbd0004, 0x03e0c821,
 
155
  /* lw caller-saved-reg, offset(sp) */
 
156
  0x8fbe0024, 0x8fb70020, 0x8fb6001c, 0x8fb50018, 0x8fb40014, 0x8fb30010,
 
157
  0x8fb2000c, 0x8fb10008, 0x8fb00004, 0x8fbc0000,
 
158
#ifdef __mips_soft_float
 
159
  0x03e00008, 0x27bd0028  /* jr ra; addiu sp, sp, 10*4 */
 
160
#else
 
161
  /* ldc1 {$f20-$f30}, offset(sp) */
 
162
  0xd7be0050, 0xd7bc0048, 0xd7ba0040, 0xd7b80038, 0xd7b60030, 0xd7b40028,
 
163
  0x03e00008, 0x27bd0058  /* jr ra; addiu sp, sp, 10*4+6*8 */
 
164
#endif
 
165
};
 
166
 
 
167
typedef void *coco_ctx[2];  /* ra, sp */
 
168
#define COCO_CTX                coco_ctx
 
169
#define COCO_SWITCH(from, to) \
 
170
  ((void (*)(coco_ctx, coco_ctx))coco_switch)(from, to);
 
171
#define COCO_MAKECTX(coco, buf, func, stack, a0) \
 
172
  buf[0] = (void *)(func); \
 
173
  buf[1] = (void *)&stack[COCO_STACKSAVE]; \
 
174
  stack[4] = (size_t)(a0);  /* Assumes o32 ABI. */
 
175
#define COCO_STACKADJUST        8
 
176
#define COCO_MAIN_PARAM         int _a, int _b, int _c, int _d, lua_State *L
 
177
 
 
178
#endif /* arch check */
 
179
 
 
180
#endif /* !(__GNUC__ >= 3 && !defined(COCO_USE_SETJMP)) */
 
181
 
 
182
/* Try _setjmp/_longjmp with a patched jump buffer. */
 
183
#ifndef COCO_MAKECTX
 
184
#include <setjmp.h>
 
185
 
 
186
/* Check for supported CPU+OS combinations. */
 
187
#if defined(__i386) || defined(__i386__)
 
188
 
 
189
#define COCO_STATE_HEAD         size_t arg0;
 
190
#define COCO_SETJMP_X86(coco, stack, a0) \
 
191
  stack[COCO_STACKADJUST-1] = 0xdeadc0c0;  /* Dummy return address. */ \
 
192
  coco->arg0 = (size_t)(a0);
 
193
 
 
194
#if __GLIBC__ == 2 && defined(JB_SP)            /* x86-linux-glibc2 */
 
195
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
196
  buf->__jmpbuf[JB_PC] = (int)(func); \
 
197
  buf->__jmpbuf[JB_SP] = (int)(stack); \
 
198
  buf->__jmpbuf[JB_BP] = 0; \
 
199
  COCO_SETJMP_X86(coco, stack, a0)
 
200
#elif defined(__linux__) && defined(_I386_JMP_BUF_H)    /* x86-linux-libc5 */
 
201
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
202
  buf->__pc = (func); \
 
203
  buf->__sp = (stack); \
 
204
  buf->__bp = NULL; \
 
205
  COCO_SETJMP_X86(coco, stack, a0)
 
206
#elif defined(__FreeBSD__)                      /* x86-FreeBSD */
 
207
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
208
  buf->_jb[0] = (long)(func); \
 
209
  buf->_jb[2] = (long)(stack); \
 
210
  buf->_jb[3] = 0; /* ebp */ \
 
211
  COCO_SETJMP_X86(coco, stack, a0)
 
212
#define COCO_STACKADJUST        2
 
213
#elif defined(__NetBSD__) || defined(__OpenBSD__) /* x86-NetBSD, x86-OpenBSD */
 
214
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
215
  buf[0] = (long)(func); \
 
216
  buf[2] = (long)(stack); \
 
217
  buf[3] = 0; /* ebp */ \
 
218
  COCO_SETJMP_X86(coco, stack, a0)
 
219
#define COCO_STACKADJUST        2
 
220
#elif defined(__solaris__) && _JBLEN == 10      /* x86-solaris */
 
221
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
222
  buf[5] = (int)(func); \
 
223
  buf[4] = (int)(stack); \
 
224
  buf[3] = 0; \
 
225
  COCO_SETJMP_X86(coco, stack, a0)
 
226
#elif defined(__MACH__) && defined(_BSD_I386_SETJMP_H_) /* x86-macosx */
 
227
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
228
  buf[12] = (int)(func); \
 
229
  buf[9] = (int)(stack); \
 
230
  buf[8] = 0; /* ebp */ \
 
231
  COCO_SETJMP_X86(coco, stack, a0)
 
232
#endif
 
233
 
 
234
#elif defined(__x86_64__) || defined(__x86_64)
 
235
 
 
236
#define COCO_STATE_HEAD         size_t arg0;
 
237
 
 
238
#define COCO_MAIN_PARAM \
 
239
  int _a, int _b, int _c, int _d, int _e, int _f, lua_State *L
 
240
 
 
241
#if __GLIBC__ == 2 && defined(JB_RSP)           /* x64-linux-glibc2 */
 
242
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
243
  buf->__jmpbuf[JB_PC] = (long)(func); \
 
244
  buf->__jmpbuf[JB_RSP] = (long)(stack); \
 
245
  buf->__jmpbuf[JB_RBP] = 0; \
 
246
  stack[0] = 0xdeadc0c0;  /* Dummy return address. */ \
 
247
  coco->arg0 = (size_t)(a0);
 
248
#elif defined(__solaris__) && _JBLEN == 8               /* x64-solaris */
 
249
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
250
  buf[7] = (long)(func); \
 
251
  buf[6] = (long)(stack); \
 
252
  buf[5] = 0; \
 
253
  stack[0] = 0xdeadc0c0;  /* Dummy return address. */ \
 
254
  coco->arg0 = (size_t)(a0);
 
255
#endif
 
256
 
 
257
#elif defined(PPC) || defined(__ppc__) || defined(__PPC__) || \
 
258
      defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC)
 
259
 
 
260
#define COCO_STACKADJUST        16
 
261
#define COCO_MAIN_PARAM \
 
262
  int _a, int _b, int _c, int _d, int _e, int _f, int _g, int _h, lua_State *L
 
263
 
 
264
#if defined(__MACH__) && defined(_BSD_PPC_SETJMP_H_)    /* ppc32-macosx */
 
265
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
266
  buf[21] = (int)(func); \
 
267
  buf[0] = (int)(stack); \
 
268
  stack[6+8] = (size_t)(a0);
 
269
#endif
 
270
 
 
271
#elif (defined(MIPS) || defined(MIPSEL) || defined(__mips)) && \
 
272
  _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi)
 
273
 
 
274
/* Stack layout for o32 ABI. */
 
275
#define COCO_STACKADJUST        8
 
276
#define COCO_MAIN_PARAM         int _a, int _b, int _c, int _d, lua_State *L
 
277
 
 
278
#if __GLIBC__ == 2 || defined(__UCLIBC__)       /* mips32-linux-glibc2 */
 
279
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
280
  buf->__jmpbuf->__pc = (func); /* = t9 in _longjmp. Reqd. for -mabicalls. */ \
 
281
  buf->__jmpbuf->__sp = (stack); \
 
282
  buf->__jmpbuf->__fp = (void *)0; \
 
283
  stack[4] = (size_t)(a0);
 
284
#endif
 
285
 
 
286
#elif defined(__arm__) || defined(__ARM__)
 
287
 
 
288
#if __GLIBC__ == 2 || defined(__UCLIBC__)       /* arm-linux-glibc2 */
 
289
#define COCO_PATCHCTX(coco, buf, func, stack, a0) \
 
290
  buf->__jmpbuf[__JMP_BUF_SP+1] = (int)(func); /* pc */ \
 
291
  buf->__jmpbuf[__JMP_BUF_SP] = (int)(stack); /* sp */ \
 
292
  buf->__jmpbuf[__JMP_BUF_SP-1] = 0; /* fp */ \
 
293
  stack[0] = (size_t)(a0);
 
294
#define COCO_STACKADJUST        2
 
295
#define COCO_MAIN_PARAM         int _a, int _b, int _c, int _d, lua_State *L
 
296
#endif
 
297
 
 
298
#endif /* arch check */
 
299
 
 
300
#ifdef COCO_PATCHCTX
 
301
#define COCO_CTX                jmp_buf
 
302
#define COCO_MAKECTX(coco, buf, func, stack, a0) \
 
303
  _setjmp(buf); COCO_PATCHCTX(coco, buf, func, stack, a0)
 
304
#define COCO_SWITCH(from, to)   if (!_setjmp(from)) _longjmp(to, 1);
 
305
#endif
 
306
 
 
307
#endif /* !defined(COCO_MAKECTX) */
 
308
 
 
309
#endif /* !defined(COCO_USE_UCONTEXT) */
 
310
 
 
311
/* ------------------------------------------------------------------------ */
 
312
 
 
313
/* Use inline asm or _setjmp/_longjmp if available. */
 
314
#ifdef COCO_MAKECTX
 
315
 
 
316
#ifndef COCO_STACKADJUST
 
317
#define COCO_STACKADJUST        1
 
318
#endif
 
319
 
 
320
#define COCO_FILL(coco, NL, mainfunc) \
 
321
{ /* Include the return address to get proper stack alignment. */ \
 
322
  size_t *stackptr = &((size_t *)coco)[-COCO_STACKADJUST]; \
 
323
  COCO_MAKECTX(coco, coco->ctx, mainfunc, stackptr, NL) \
 
324
}
 
325
 
 
326
/* ------------------------------------------------------------------------ */
 
327
 
 
328
/* Else fallback to ucontext. Slower, because it saves/restores signals. */
 
329
#else /* !defined(COCO_MAKECTX) */
 
330
 
 
331
#include <ucontext.h>
 
332
 
 
333
#define COCO_CTX                ucontext_t
 
334
 
 
335
/* Ugly workaround for makecontext() deficiencies on 64 bit CPUs. */
 
336
/* Note that WIN64 (which is LLP64) never comes here. See above. */
 
337
#if defined(__LP64__) || defined(_LP64) || INT_MAX != LONG_MAX
 
338
/* 64 bit CPU: split the pointer into two 32 bit ints. */
 
339
#define COCO_MAIN_PARAM         unsigned int lo, unsigned int hi
 
340
#define COCO_MAIN_GETL \
 
341
  lua_State *L = (lua_State *)((((unsigned long)hi)<<32)+(unsigned long)lo);
 
342
#define COCO_MAKECTX(coco, NL, mainfunc) \
 
343
  makecontext(&coco->ctx, mainfunc, 2, \
 
344
    (int)(ptrdiff_t)NL, (int)((ptrdiff_t)NL>>32));
 
345
#else
 
346
/* 32 bit CPU: a pointer fits into an int. */
 
347
#define COCO_MAKECTX(coco, NL, mainfunc) \
 
348
  makecontext(&coco->ctx, mainfunc, 1, (int)NL);
 
349
#endif
 
350
 
 
351
#define COCO_FILL(coco, NL, mainfunc) \
 
352
  getcontext(&coco->ctx); \
 
353
  coco->ctx.uc_link = NULL;  /* We never exit from coco_main. */ \
 
354
  coco->ctx.uc_stack.ss_sp = coco->allocptr; \
 
355
  coco->ctx.uc_stack.ss_size = (char *)coco - (char *)(coco->allocptr); \
 
356
  COCO_MAKECTX(coco, NL, mainfunc)
 
357
 
 
358
#define COCO_SWITCH(from, to)   swapcontext(&(from), &(to));
 
359
 
 
360
#endif /* !defined(COCO_MAKECTX) */
 
361
 
 
362
 
 
363
/* Common code for inline asm/setjmp/ucontext to allocate/free the stack. */
 
364
 
 
365
struct coco_State {
 
366
#ifdef COCO_STATE_HEAD
 
367
  COCO_STATE_HEAD
 
368
#endif
 
369
  COCO_CTX ctx;                 /* Own context. */
 
370
  COCO_CTX back;                /* Context to switch back to. */
 
371
  void *allocptr;               /* Pointer to allocated memory. */
 
372
  int allocsize;                /* Size of allocated memory. */
 
373
  int nargs;                    /* Number of arguments to pass. */
 
374
  STACK_VGID                    /* Optional valgrind stack id. See above. */
 
375
};
 
376
 
 
377
typedef void (*coco_MainFunc)(void);
 
378
 
 
379
/* Put the Coco state at the end and align it downwards. */
 
380
#define ALIGNED_END(p, s, t) \
 
381
  ((t *)(((char *)0) + ((((char *)(p)-(char *)0)+(s)-sizeof(t)) & -16)))
 
382
 
 
383
/* TODO: use mmap. */
 
384
#define COCO_NEW(OL, NL, cstacksize, mainfunc) \
 
385
{ \
 
386
  void *ptr = luaM_malloc(OL, cstacksize); \
 
387
  coco_State *coco = ALIGNED_END(ptr, cstacksize, coco_State); \
 
388
  STACK_REG(coco, ptr, cstacksize) \
 
389
  coco->allocptr = ptr; \
 
390
  coco->allocsize = cstacksize; \
 
391
  COCO_FILL(coco, NL, mainfunc) \
 
392
  L2COCO(NL) = coco; \
 
393
}
 
394
 
 
395
#define COCO_FREE(L) \
 
396
  STACK_DEREG(L2COCO(L)) \
 
397
  luaM_freemem(L, L2COCO(L)->allocptr, L2COCO(L)->allocsize); \
 
398
  L2COCO(L) = NULL;
 
399
 
 
400
#define COCO_JUMPIN(coco)       COCO_SWITCH(coco->back, coco->ctx)
 
401
#define COCO_JUMPOUT(coco)      COCO_SWITCH(coco->ctx, coco->back)
 
402
 
 
403
#endif /* !COCO_USE_FIBERS */
 
404
 
 
405
/* ------------------------------------------------------------------------ */
 
406
 
 
407
#ifndef COCO_MIN_CSTACKSIZE
 
408
#define COCO_MIN_CSTACKSIZE             (32768+4096)
 
409
#endif
 
410
 
 
411
/* Don't use multiples of 64K to avoid D-cache aliasing conflicts. */
 
412
#ifndef COCO_DEFAULT_CSTACKSIZE
 
413
#define COCO_DEFAULT_CSTACKSIZE         (65536-4096)
 
414
#endif
 
415
 
 
416
static int defaultcstacksize = COCO_DEFAULT_CSTACKSIZE;
 
417
 
 
418
/* Start the Lua or C function. */
 
419
static void coco_start(lua_State *L, void *ud)
 
420
{
 
421
  if (luaD_precall(L, (StkId)ud, LUA_MULTRET) == PCRLUA)
 
422
    luaV_execute(L, L->ci - L->base_ci);
 
423
}
 
424
 
 
425
#ifndef COCO_MAIN_PARAM
 
426
#define COCO_MAIN_PARAM         lua_State *L
 
427
#endif
 
428
 
 
429
#ifndef COCO_MAIN_DECL
 
430
#define COCO_MAIN_DECL
 
431
#endif
 
432
 
 
433
/* Toplevel function for the new coroutine stack. Never exits. */
 
434
static void COCO_MAIN_DECL coco_main(COCO_MAIN_PARAM)
 
435
{
 
436
#ifdef COCO_MAIN_GETL
 
437
  COCO_MAIN_GETL
 
438
#endif
 
439
  coco_State *coco = L2COCO(L);
 
440
  for (;;) {
 
441
    L->status = luaD_rawrunprotected(L, coco_start, L->top - (coco->nargs+1));
 
442
    if (L->status != 0) luaD_seterrorobj(L, L->status, L->top);
 
443
    COCO_JUMPOUT(coco)
 
444
  }
 
445
}
 
446
 
 
447
/* Add a C stack to a coroutine. */
 
448
lua_State *lua_newcthread(lua_State *OL, int cstacksize)
 
449
{
 
450
  lua_State *NL = lua_newthread(OL);
 
451
 
 
452
  if (cstacksize < 0)
 
453
    return NL;
 
454
  if (cstacksize == 0)
 
455
    cstacksize = defaultcstacksize;
 
456
  else if (cstacksize < COCO_MIN_CSTACKSIZE)
 
457
    cstacksize = COCO_MIN_CSTACKSIZE;
 
458
  cstacksize &= -16;
 
459
 
 
460
  COCO_NEW(OL, NL, cstacksize, ((coco_MainFunc)(coco_main)))
 
461
 
 
462
  return NL;
 
463
}
 
464
 
 
465
/* Free the C stack of a coroutine. Called from lstate.c. */
 
466
void luaCOCO_free(lua_State *L)
 
467
{
 
468
  COCO_FREE(L)
 
469
}
 
470
 
 
471
/* Resume a coroutine with a C stack. Called from ldo.c. */
 
472
int luaCOCO_resume(lua_State *L, int nargs)
 
473
{
 
474
  coco_State *coco = L2COCO(L);
 
475
  coco->nargs = nargs;
 
476
  COCO_JUMPIN(coco)
 
477
#ifndef COCO_DISABLE_EARLY_FREE
 
478
  if (L->status != LUA_YIELD) {
 
479
    COCO_FREE(L)
 
480
  }
 
481
#endif
 
482
  return L->status;
 
483
}
 
484
 
 
485
/* Yield from a coroutine with a C stack. Called from ldo.c. */
 
486
int luaCOCO_yield(lua_State *L)
 
487
{
 
488
  coco_State *coco = L2COCO(L);
 
489
  L->status = LUA_YIELD;
 
490
  COCO_JUMPOUT(coco)
 
491
  L->status = 0;
 
492
  {
 
493
    StkId base = L->top - coco->nargs;
 
494
    StkId rbase = L->base;
 
495
    if (rbase < base) {  /* Need to move args down? */
 
496
      while (base < L->top)
 
497
        setobjs2s(L, rbase++, base++);
 
498
      L->top = rbase;
 
499
    }
 
500
  }
 
501
  L->base = L->ci->base;  /* Restore invariant. */
 
502
  return coco->nargs;
 
503
}
 
504
 
 
505
/* Get/set the default C stack size. */
 
506
int luaCOCO_cstacksize(int cstacksize)
 
507
{
 
508
  int oldsz = defaultcstacksize;
 
509
  if (cstacksize >= 0) {
 
510
    if (cstacksize == 0)
 
511
      cstacksize = COCO_DEFAULT_CSTACKSIZE;
 
512
    else if (cstacksize < COCO_MIN_CSTACKSIZE)
 
513
      cstacksize = COCO_MIN_CSTACKSIZE;
 
514
    defaultcstacksize = cstacksize;
 
515
  }
 
516
  return oldsz;
 
517
}
 
518
 
 
519
#endif