diff options
author | Sjoerd Mullender <sjoerd@acm.org> | 1993-01-06 13:36:38 (GMT) |
---|---|---|
committer | Sjoerd Mullender <sjoerd@acm.org> | 1993-01-06 13:36:38 (GMT) |
commit | ed59d205a94747ad57f78ae35f46837a994da8cb (patch) | |
tree | 554f575cfa4887217b826e1b96d6456246854041 /Modules | |
parent | fea2af1e9b0c99cac6cb8806c4af651a38e92d07 (diff) | |
download | cpython-ed59d205a94747ad57f78ae35f46837a994da8cb.zip cpython-ed59d205a94747ad57f78ae35f46837a994da8cb.tar.gz cpython-ed59d205a94747ad57f78ae35f46837a994da8cb.tar.bz2 |
Various changes.
* Makefile: svmodule.c.proto and svgen.py are gone, svmodule.c came in
their stead. Also, pass -DUSE_DL flag to thread.c and give
the user a possibility to add the -DDEBUG to just thread.c.
* ceval.c: init_save_thread() can be called more than once now.
* svgen.py, svmodule.c.proto, svmodule.c: Removed prototype file and
replaced it by the generated file.
* thread.c: Added some more checks; added call to DL library when it
is also used to tell it where the shared arena is so that DL
can use some other area.
* threadmodule.c: Call init_save_thread from another place. Also,
added new function getlocklock() which does to lock objects
what getfilefile does to file objects.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/svmodule.c | 952 | ||||
-rw-r--r-- | Modules/threadmodule.c | 15 |
2 files changed, 964 insertions, 3 deletions
diff --git a/Modules/svmodule.c b/Modules/svmodule.c new file mode 100644 index 0000000..6df8b95 --- /dev/null +++ b/Modules/svmodule.c @@ -0,0 +1,952 @@ +/********************************************************** +Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The +Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* SV module -- interface to the Indigo video board */ + +#include <sys/time.h> +#include <svideo.h> +#include "allobjects.h" +#include "import.h" +#include "modsupport.h" +#include "compile.h" +#include "ceval.h" + +typedef struct { + OB_HEAD + SV_nodeP ob_svideo; + svCaptureInfo ob_info; +} svobject; + +typedef struct { + OB_HEAD + void *ob_capture; + int ob_mustunlock; + svCaptureInfo ob_info; + svobject *ob_svideo; +} captureobject; + +static object *SvError; /* exception sv.error */ + +static object *newcaptureobject PROTO((svobject *, void *, int)); + +/* Set a SV-specific error from svideo_errno and return NULL */ +static object * +sv_error() +{ + err_setstr(SvError, svStrerror(svideo_errno)); + return NULL; +} + +static object * +svc_conversion(self, args, function, factor) + captureobject *self; + object *args; + void (*function)(); + int factor; +{ + object *output; + int invert; + + if (!getargs(args, "i", &invert)) + return NULL; + + output = newsizedstringobject(NULL, self->ob_info.width * self->ob_info.height * factor); + if (output == NULL) + return NULL; + + (*function)((boolean) invert, self->ob_capture, getstringvalue(output), + self->ob_info.width, self->ob_info.height); + + return output; +} + +static object * +svc_YUVtoRGB(self, args) + captureobject *self; + object *args; +{ + switch (self->ob_info.format) { + case SV_YUV411_FRAMES: + case SV_YUV411_FRAMES_AND_BLANKING_BUFFER: + break; + default: + err_setstr(SvError, "data had bad format"); + return NULL; + } + return svc_conversion(self, args, svYUVtoRGB, sizeof(long)); +} + +static object * +svc_RGB8toRGB32(self, args) + captureobject *self; + object *args; +{ + if (self->ob_info.format != SV_RGB8_FRAMES) { + err_setstr(SvError, "data has bad format"); + return NULL; + } + return svc_conversion(self, args, svRGB8toRGB32, sizeof(long)); +} + +static object * +svc_InterleaveFields(self, args) + captureobject *self; + object *args; +{ + if (self->ob_info.format != SV_RGB8_FRAMES) { + err_setstr(SvError, "data has bad format"); + return NULL; + } + return svc_conversion(self, args, svInterleaveFields, 1); +} + +static object * +svc_GetFields(self, args) + captureobject *self; + object *args; +{ + object *f1, *f2; + int fieldsize; + + if (self->ob_info.format != SV_RGB8_FRAMES) { + err_setstr(SvError, "data has bad format"); + return NULL; + } + + fieldsize = self->ob_info.width * self->ob_info.height / 2; + f1 = newsizedstringobject((char *) self->ob_capture, fieldsize); + if (f1 == NULL) + return NULL; + f2 = newsizedstringobject((char *) self->ob_capture + fieldsize, fieldsize); + if (f2 == NULL) { + DECREF(f1); + return NULL; + } + return mkvalue("(OO)", f1, f2); +} + +static object * +svc_UnlockCaptureData(self, args) + captureobject *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + + if (!self->ob_mustunlock) { + err_setstr(SvError, "buffer should not be unlocked"); + return NULL; + } + + if (svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture)) + return sv_error(); + + self->ob_mustunlock = 0; + + INCREF(None); + return None; +} + +#ifdef USE_GL +#include <gl.h> + +static object * +svc_lrectwrite(self, args) + captureobject *self; + object *args; +{ + Screencoord x1, x2, y1, y2; + + if (!getargs(args, "(hhhh)", &x1, &x2, &y1, &y2)) + return NULL; + + lrectwrite(x1, x2, y1, y2, (unsigned long *) self->ob_capture); + + INCREF(None); + return None; +} +#endif + +static object * +writefile(self, args) + captureobject *self; + object *args; +{ + object *file; + int size; + + if (!getargs(args, "O", &file)) + return NULL; + + if (!is_fileobject(file)) { + err_setstr(SvError, "not a file object"); + return NULL; + } + + size = self->ob_info.width * self->ob_info.height; + + if (fwrite(self->ob_capture, sizeof(long), size, getfilefile(file)) != size) { + err_setstr(SvError, "writing failed"); + return NULL; + } + + INCREF(None); + return None; +} + +static object * +svc_FindVisibleRegion(self, args) + captureobject *self; + object *args; +{ + void *visible; + int width; + + if (!getnoarg(args)) + return NULL; + + if (svFindVisibleRegion(self->ob_svideo->ob_svideo, self->ob_capture, &visible, self->ob_info.width)) + return sv_error(); + + if (visible == NULL) { + err_setstr(SvError, "data in wrong format"); + return NULL; + } + + return newcaptureobject(self->ob_svideo, visible, 0); +} + +static struct methodlist capture_methods[] = { + {"YUVtoRGB", svc_YUVtoRGB}, + {"RGB8toRGB32", svc_RGB8toRGB32}, + {"InterleaveFields", svc_InterleaveFields}, + {"UnlockCaptureData", svc_UnlockCaptureData}, + {"FindVisibleRegion", svc_FindVisibleRegion}, + {"GetFields", svc_GetFields}, +#ifdef USE_GL + {"lrectwrite", svc_lrectwrite}, +#endif + {"writefile", writefile}, + {NULL, NULL} /* sentinel */ +}; + +static void +capture_dealloc(self) + captureobject *self; +{ + if (self->ob_capture != NULL) { + if (self->ob_mustunlock) + (void) svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture); + self->ob_capture = NULL; + DECREF(self->ob_svideo); + self->ob_svideo = NULL; + } + DEL(self); +} + +static object * +capture_getattr(self, name) + svobject *self; + char *name; +{ + return findmethod(capture_methods, (object *)self, name); +} + +typeobject Capturetype = { + OB_HEAD_INIT(&Typetype) + 0, /*ob_size*/ + "capture", /*tp_name*/ + sizeof(captureobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + capture_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + capture_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ +}; + +static object * +newcaptureobject(self, ptr, mustunlock) + svobject *self; + void *ptr; + int mustunlock; +{ + captureobject *p; + + p = NEWOBJ(captureobject, &Capturetype); + if (p == NULL) + return NULL; + p->ob_svideo = self; + INCREF(self); + p->ob_capture = ptr; + p->ob_mustunlock = mustunlock; + p->ob_info = self->ob_info; + return (object *) p; +} + +static object * +sv_GetCaptureData(self, args) + svobject *self; + object *args; +{ + void *ptr; + long fieldID; + object *res, *c; + + if (!getnoarg(args)) + return NULL; + + if (svGetCaptureData(self->ob_svideo, &ptr, &fieldID)) + return sv_error(); + + if (ptr == NULL) { + err_setstr(SvError, "no data available"); + return NULL; + } + + c = newcaptureobject(self, ptr, 1); + if (c == NULL) + return NULL; + res = mkvalue("(Oi)", c, fieldID); + DECREF(c); + return res; +} + +static object * +sv_BindGLWindow(self, args) + svobject *self; + object *args; +{ + long wid; + int mode; + + if (!getargs(args, "(ii)", &wid, &mode)) + return NULL; + + if (svBindGLWindow(self->ob_svideo, wid, mode)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_EndContinuousCapture(self, args) + svobject *self; + object *args; +{ + + if (!getnoarg(args)) + return NULL; + + if (svEndContinuousCapture(self->ob_svideo)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_IsVideoDisplayed(self, args) + svobject *self; + object *args; +{ + int v; + + if (!getnoarg(args)) + return NULL; + + v = svIsVideoDisplayed(self->ob_svideo); + if (v == -1) + return sv_error(); + + return newintobject((long) v); +} + +static object * +sv_OutputOffset(self, args) + svobject *self; + object *args; +{ + int x_offset; + int y_offset; + + if (!getargs(args, "(ii)", &x_offset, &y_offset)) + return NULL; + + if (svOutputOffset(self->ob_svideo, x_offset, y_offset)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_PutFrame(self, args) + svobject *self; + object *args; +{ + char *buffer; + + if (!getargs(args, "s", &buffer)) + return NULL; + + if (svPutFrame(self->ob_svideo, buffer)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_QuerySize(self, args) + svobject *self; + object *args; +{ + int w; + int h; + int rw; + int rh; + + if (!getargs(args, "(ii)", &w, &h)) + return NULL; + + if (svQuerySize(self->ob_svideo, w, h, &rw, &rh)) + return sv_error(); + + return mkvalue("(ii)", (long) rw, (long) rh); +} + +static object * +sv_SetSize(self, args) + svobject *self; + object *args; +{ + int w; + int h; + + if (!getargs(args, "(ii)", &w, &h)) + return NULL; + + if (svSetSize(self->ob_svideo, w, h)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_SetStdDefaults(self, args) + svobject *self; + object *args; +{ + + if (!getnoarg(args)) + return NULL; + + if (svSetStdDefaults(self->ob_svideo)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_UseExclusive(self, args) + svobject *self; + object *args; +{ + boolean onoff; + int mode; + + if (!getargs(args, "(ii)", &onoff, &mode)) + return NULL; + + if (svUseExclusive(self->ob_svideo, onoff, mode)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_WindowOffset(self, args) + svobject *self; + object *args; +{ + int x_offset; + int y_offset; + + if (!getargs(args, "(ii)", &x_offset, &y_offset)) + return NULL; + + if (svWindowOffset(self->ob_svideo, x_offset, y_offset)) + return sv_error(); + + INCREF(None); + return None; +} + +static object * +sv_CaptureBurst(self, args) + svobject *self; + object *args; +{ + int bytes, i; + svCaptureInfo info; + void *bitvector = NULL; + object *videodata, *bitvecobj, *res; + static object *evenitem, *odditem; + + if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height, + &info.size, &info.samplingrate)) + return NULL; + + switch (info.format) { + case SV_RGB8_FRAMES: + bitvector = malloc(SV_BITVEC_SIZE(info.size)); + break; + case SV_YUV411_FRAMES_AND_BLANKING_BUFFER: + break; + default: + err_setstr(SvError, "illegal format specified"); + return NULL; + } + + if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) { + if (bitvector) + free(bitvector); + return sv_error(); + } + + videodata = newsizedstringobject(NULL, bytes); + if (videodata == NULL) { + if (bitvector) + free(bitvector); + return NULL; + } + + /* XXX -- need to do something about the bitvector */ + if (svCaptureBurst(self->ob_svideo, &info, getstringvalue(videodata), + bitvector)) { + if (bitvector) + free(bitvector); + DECREF(videodata); + return sv_error(); + } + + if (bitvector) { + if (evenitem == NULL) { + evenitem = newintobject(0); + if (evenitem == NULL) { + free(bitvector); + DECREF(videodata); + return NULL; + } + } + if (odditem == NULL) { + odditem = newintobject(1); + if (odditem == NULL) { + free(bitvector); + DECREF(videodata); + return NULL; + } + } + bitvecobj = newtupleobject(2 * info.size); + if (bitvecobj == NULL) { + free(bitvecobj); + DECREF(videodata); + return NULL; + } + for (i = 0; i < 2 * info.size; i++) { + if (SV_GET_FIELD(bitvector, i) == SV_EVEN_FIELD) { + INCREF(evenitem); + settupleitem(bitvecobj, i, evenitem); + } else { + INCREF(odditem); + settupleitem(bitvecobj, i, odditem); + } + } + free(bitvector); + } else { + bitvecobj = None; + INCREF(None); + } + + res = mkvalue("((iiiii)OO)", info.format, info.width, info.height, + info.size, info.samplingrate, videodata, bitvecobj); + DECREF(videodata); + DECREF(bitvecobj); + return res; +} + +static object * +sv_CaptureOneFrame(self, args) + svobject *self; + object *args; +{ + svCaptureInfo info; + int format, width, height; + int bytes; + object *videodata, *res; + + if (!getargs(args, "(iii)", &format, &width, &height)) + return NULL; + info.format = format; + info.width = width; + info.height = height; + info.size = 0; + info.samplingrate = 0; + if (svQueryCaptureBufferSize(self->ob_svideo, &info, &bytes)) + return sv_error(); + videodata = newsizedstringobject(NULL, bytes); + if (videodata == NULL) + return NULL; + if (svCaptureOneFrame(self->ob_svideo, format, &width, &height, + getstringvalue(videodata))) { + DECREF(videodata); + return sv_error(); + } + + res = mkvalue("(iiO)", width, height, videodata); + DECREF(videodata); + return res; +} + +static object * +sv_InitContinuousCapture(self, args) + svobject *self; + object *args; +{ + svCaptureInfo info; + + if (!getargs(args, "(iiiii)", &info.format, &info.width, &info.height, + &info.size, &info.samplingrate)) + return NULL; + + if (svInitContinuousCapture(self->ob_svideo, &info)) + return sv_error(); + + self->ob_info = info; + + return mkvalue("(iiiii)", info.format, info.width, info.height, + info.size, info.samplingrate); +} + +static object * +sv_LoadMap(self, args) + svobject *self; + object *args; +{ + object *rgb, *v, *cell; + rgb_tuple *mapp; + int maptype; + int i, j; /* indices */ + + if (!getargs(args, "(iO)", &maptype, &rgb)) + return NULL; + if (!is_listobject(rgb) || getlistsize(rgb) != 256) { + err_badarg(); + return NULL; + } + mapp = NEW(rgb_tuple, 256); + if (mapp == NULL) + return err_nomem(); + for (i = 0; i < 256; i++) { + v = getlistitem(rgb, i); + if (!is_tupleobject(v) || gettuplesize(v) != 3) { + DEL(mapp); + err_badarg(); + return NULL; + } + for (j = 0; j < 3; j++) { + cell = gettupleitem(v, j); + if (!is_intobject(cell)) { + DEL(mapp); + err_badarg(); + return NULL; + } + switch (j) { + case 0: mapp[i].red = getintvalue(cell); break; + case 1: mapp[i].blue = getintvalue(cell); break; + case 2: mapp[i].green = getintvalue(cell); break; + } + } + } + + if (svLoadMap(self->ob_svideo, maptype, mapp)) { + DEL(mapp); + return sv_error(); + } + + DEL(mapp); + + INCREF(None); + return None; +} + +static object * +sv_CloseVideo(self, args) + svobject *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + + if (svCloseVideo(self->ob_svideo)) + return sv_error(); + self->ob_svideo = NULL; + + INCREF(None); + return None; +} + +static object * +doParams(self, args, func, modified) + svobject *self; + object *args; + int (*func)(SV_nodeP, long *, int); + int modified; +{ + object *list, *v; + long *PVbuffer; + long length; + int i; + + if (!getargs(args, "O", &list)) + return NULL; + if (!is_listobject(list)) { + err_badarg(); + return NULL; + } + length = getlistsize(list); + PVbuffer = NEW(long, length); + if (PVbuffer == NULL) + return err_nomem(); + for (i = 0; i < length; i++) { + v = getlistitem(list, i); + if (!is_intobject(v)) { + DEL(PVbuffer); + err_badarg(); + return NULL; + } + PVbuffer[i] = getintvalue(v); + } + + if ((*func)(self->ob_svideo, PVbuffer, length)) { + DEL(PVbuffer); + return sv_error(); + } + + if (modified) { + for (i = 0; i < length; i++) + setlistitem(list, i, newintobject(PVbuffer[i])); + } + + DEL(PVbuffer); + + INCREF(None); + return None; +} + +static object * +sv_GetParam(self, args) + object *self, *args; +{ + return doParams(self, args, svGetParam, 1); +} + +static object * +sv_GetParamRange(self, args) + object *self, *args; +{ + return doParams(self, args, svGetParamRange, 1); +} + +static object * +sv_SetParam(self, args) + object *self, *args; +{ + return doParams(self, args, svSetParam, 0); +} + +static struct methodlist svideo_methods[] = { + {"BindGLWindow", sv_BindGLWindow}, + {"EndContinuousCapture",sv_EndContinuousCapture}, + {"IsVideoDisplayed", sv_IsVideoDisplayed}, + {"OutputOffset", sv_OutputOffset}, + {"PutFrame", sv_PutFrame}, + {"QuerySize", sv_QuerySize}, + {"SetSize", sv_SetSize}, + {"SetStdDefaults", sv_SetStdDefaults}, + {"UseExclusive", sv_UseExclusive}, + {"WindowOffset", sv_WindowOffset}, + {"InitContinuousCapture",sv_InitContinuousCapture}, + {"CaptureBurst", sv_CaptureBurst}, + {"CaptureOneFrame", sv_CaptureOneFrame}, + {"GetCaptureData", sv_GetCaptureData}, + {"CloseVideo", sv_CloseVideo}, + {"LoadMap", sv_LoadMap}, + {"GetParam", sv_GetParam}, + {"GetParamRange", sv_GetParamRange}, + {"SetParam", sv_SetParam}, + {NULL, NULL} /* sentinel */ +}; + +static object * +sv_conversion(self, args, function, inputfactor, factor) + object *self, *args; + void (*function)(); + int inputfactor, factor; +{ + int invert, width, height, inputlength; + char *input; + object *output; + + if (!getargs(args, "(is#ii)", &invert, &input, &inputlength, &width, &height)) + return NULL; + + if (width * height * inputfactor > inputlength) { + err_setstr(SvError, "input buffer not long enough"); + return NULL; + } + + output = newsizedstringobject(NULL, width * height * factor); + if (output == NULL) + return NULL; + + (*function)(invert, input, getstringvalue(output), width, height); + + return output; +} + +static object * +sv_InterleaveFields(self, args) + object *self, *args; +{ + return sv_conversion(self, args, svInterleaveFields, 1, 1); +} + +static object * +sv_RGB8toRGB32(self, args) + object *self, *args; +{ + return sv_conversion(self, args, svRGB8toRGB32, 1, sizeof(long)); +} + +static object * +sv_YUVtoRGB(self, args) + object *self, *args; +{ + return sv_conversion(self, args, svYUVtoRGB, 2, sizeof(long)); +} + +static void +svideo_dealloc(self) + svobject *self; +{ + if (self->ob_svideo != NULL) + (void) svCloseVideo(self->ob_svideo); + DEL(self); +} + +static object * +svideo_getattr(self, name) + svobject *self; + char *name; +{ + return findmethod(svideo_methods, (object *)self, name); +} + +typeobject Svtype = { + OB_HEAD_INIT(&Typetype) + 0, /*ob_size*/ + "sv", /*tp_name*/ + sizeof(svobject), /*tp_size*/ + 0, /*tp_itemsize*/ + /* methods */ + svideo_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + svideo_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ +}; + +static object * +newsvobject(svp) + SV_nodeP svp; +{ + svobject *p; + + p = NEWOBJ(svobject, &Svtype); + if (p == NULL) + return NULL; + p->ob_svideo = svp; + p->ob_info.format = 0; + p->ob_info.size = 0; + p->ob_info.width = 0; + p->ob_info.height = 0; + p->ob_info.samplingrate = 0; + return (object *) p; +} + +static object * +sv_OpenVideo(self, args) + object *self, *args; +{ + SV_nodeP svp; + + if (!getnoarg(args)) + return NULL; + + svp = svOpenVideo(); + if (svp == NULL) + return sv_error(); + + return newsvobject(svp); +} + +static struct methodlist sv_methods[] = { + {"InterleaveFields", sv_InterleaveFields}, + {"RGB8toRGB32", sv_RGB8toRGB32}, + {"YUVtoRGB", sv_YUVtoRGB}, + {"OpenVideo", sv_OpenVideo}, + {NULL, NULL} /* Sentinel */ +}; + +void +initsv() +{ + object *m, *d; + + m = initmodule("sv", sv_methods); + d = getmoduledict(m); + + SvError = newstringobject("sv.error"); + if (SvError == NULL || dictinsert(d, "error", SvError) != 0) + fatal("can't define sv.error"); +} diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c index c2d67fc..123c4d3 100644 --- a/Modules/threadmodule.c +++ b/Modules/threadmodule.c @@ -47,6 +47,16 @@ extern typeobject Locktype; /* Really static, forward */ #define is_lockobject(v) ((v)->ob_type == &Locktype) +type_lock +getlocklock(lock) + object *lock; +{ + if (lock == NULL || !is_lockobject(lock)) + return NULL; + else + return ((lockobject *) lock)->lock_lock; +} + static lockobject * newlockobject() { @@ -204,6 +214,8 @@ thread_start_new_thread(self, args) if (!getargs(args, "(OO)", &func, &arg)) return NULL; INCREF(args); + /* Initialize the interpreter's stack save/restore mechanism */ + init_save_thread(); if (!start_new_thread(t_bootstrap, (void*) args)) { DECREF(args); err_setstr(ThreadError, "can't start new thread\n"); @@ -282,7 +294,4 @@ initthread() /* Initialize the C thread library */ init_thread(); - - /* Initialize the interpreter's stack save/restore mechanism */ - init_save_thread(); } |