*** marshal.c Tue Jul 30 07:44:44 2002 --- marshal.c.new Sat Jul 12 14:51:45 2003 *************** *** 48,53 **** --- 48,108 ---- else if ((p)->ptr != (p)->end) *(p)->ptr++ = (c); \ else w_more(c, p) + /* Locking primitives to make marshalling thread-safe in critical sections. */ + + #ifdef WITH_THREAD + + #include "pythread.h" + + static PyThread_type_lock marshal_lock = 0; + static long marshal_lock_thread = -1; + static int marshal_lock_level = 0; + + static void + lock_marshal(void) + { + long me = PyThread_get_thread_ident(); + if (me == -1) + return; /* Too bad */ + if (marshal_lock == NULL) + marshal_lock = PyThread_allocate_lock(); + if (marshal_lock_thread == me) { + marshal_lock_level++; + return; + } + if (marshal_lock_thread != -1 || !PyThread_acquire_lock(marshal_lock, 0)) + { + PyThreadState *tstate = PyEval_SaveThread(); + PyThread_acquire_lock(marshal_lock, 1); + PyEval_RestoreThread(tstate); + } + marshal_lock_thread = me; + marshal_lock_level = 1; + } + + static int + unlock_marshal(void) + { + long me = PyThread_get_thread_ident(); + if (me == -1) + return 0; /* Too bad */ + if (marshal_lock_thread != me) + return -1; + marshal_lock_level--; + if (marshal_lock_level == 0) { + marshal_lock_thread = -1; + PyThread_release_lock(marshal_lock); + } + return 1; + } + + #else + + #define lock_marshal() + #define unlock_marshal() 0 + + #endif + static void w_more(int c, WFILE *p) { *************** *** 682,695 **** * CAUTION: since this may read the entire remainder of the file, don't * call it unless you know you're done with the file. */ PyObject * PyMarshal_ReadLastObjectFromFile(FILE *fp) { - /* 75% of 2.1's .pyc files can exploit SMALL_FILE_LIMIT. - * REASONABLE_FILE_LIMIT is by defn something big enough for Tkinter.pyc. - */ - #define SMALL_FILE_LIMIT (1L << 14) - #define REASONABLE_FILE_LIMIT (1L << 18) #ifdef HAVE_FSTAT off_t filesize; #endif --- 737,750 ---- * CAUTION: since this may read the entire remainder of the file, don't * call it unless you know you're done with the file. */ + #ifdef HAVE_FSTAT + #define READ_OBJECT_BUFSIZE 0x40000 + static char read_object_buf[READ_OBJECT_BUFSIZE]; + #endif + PyObject * PyMarshal_ReadLastObjectFromFile(FILE *fp) { #ifdef HAVE_FSTAT off_t filesize; #endif *************** *** 699,729 **** } #ifdef HAVE_FSTAT filesize = getfilesize(fp); ! if (filesize > 0) { ! char buf[SMALL_FILE_LIMIT]; ! char* pBuf = NULL; ! if (filesize <= SMALL_FILE_LIMIT) ! pBuf = buf; ! else if (filesize <= REASONABLE_FILE_LIMIT) ! pBuf = (char *)PyMem_MALLOC(filesize); ! if (pBuf != NULL) { ! PyObject* v; ! size_t n = fread(pBuf, 1, filesize, fp); ! v = PyMarshal_ReadObjectFromString(pBuf, n); ! if (pBuf != buf) ! PyMem_FREE(pBuf); ! return v; } } #endif /* We don't have fstat, or we do but the file is larger than ! * REASONABLE_FILE_LIMIT or malloc failed -- read a byte at a time. */ return PyMarshal_ReadObjectFromFile(fp); - - #undef SMALL_FILE_LIMIT - #undef REASONABLE_FILE_LIMIT } PyObject * --- 754,778 ---- } #ifdef HAVE_FSTAT filesize = getfilesize(fp); ! if (filesize > 0 && filesize <= READ_OBJECT_BUFSIZE) { ! size_t n; ! PyObject* v; ! lock_marshal(); ! n = fread(read_object_buf, 1, filesize, fp); ! v = PyMarshal_ReadObjectFromString(read_object_buf, n); ! if (unlock_marshal() < 0) { ! PyErr_SetString(PyExc_RuntimeError, ! "not holding the marshal lock"); ! return NULL; } + return v; } #endif /* We don't have fstat, or we do but the file is larger than ! * READ_OBJECT_BUFSIZE -- read a byte at a time. */ return PyMarshal_ReadObjectFromFile(fp); } PyObject *