Recorded merge of revisions 81029 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines

  Untabify C files. Will watch buildbots.
........
This commit is contained in:
Antoine Pitrou 2010-05-09 15:15:40 +00:00
parent ba32864b2d
commit c7c96a90bc
321 changed files with 195492 additions and 195492 deletions

File diff suppressed because it is too large Load diff

View file

@ -4,61 +4,61 @@
asdl_seq *
asdl_seq_new(int size, PyArena *arena)
{
asdl_seq *seq = NULL;
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
asdl_seq *seq = NULL;
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
/* check size is sane */
if (size < 0 || size == INT_MIN ||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
PyErr_NoMemory();
return NULL;
}
/* check size is sane */
if (size < 0 || size == INT_MIN ||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
PyErr_NoMemory();
return NULL;
}
/* check if size can be added safely */
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
PyErr_NoMemory();
return NULL;
}
/* check if size can be added safely */
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
PyErr_NoMemory();
return NULL;
}
n += sizeof(asdl_seq);
n += sizeof(asdl_seq);
seq = (asdl_seq *)PyArena_Malloc(arena, n);
if (!seq) {
PyErr_NoMemory();
return NULL;
}
memset(seq, 0, n);
seq->size = size;
return seq;
seq = (asdl_seq *)PyArena_Malloc(arena, n);
if (!seq) {
PyErr_NoMemory();
return NULL;
}
memset(seq, 0, n);
seq->size = size;
return seq;
}
asdl_int_seq *
asdl_int_seq_new(int size, PyArena *arena)
{
asdl_int_seq *seq = NULL;
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
asdl_int_seq *seq = NULL;
size_t n = (size ? (sizeof(void *) * (size - 1)) : 0);
/* check size is sane */
if (size < 0 || size == INT_MIN ||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
PyErr_NoMemory();
return NULL;
}
/* check size is sane */
if (size < 0 || size == INT_MIN ||
(size && ((size - 1) > (PY_SIZE_MAX / sizeof(void *))))) {
PyErr_NoMemory();
return NULL;
}
/* check if size can be added safely */
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
PyErr_NoMemory();
return NULL;
}
/* check if size can be added safely */
if (n > PY_SIZE_MAX - sizeof(asdl_seq)) {
PyErr_NoMemory();
return NULL;
}
n += sizeof(asdl_seq);
n += sizeof(asdl_seq);
seq = (asdl_int_seq *)PyArena_Malloc(arena, n);
if (!seq) {
PyErr_NoMemory();
return NULL;
}
memset(seq, 0, n);
seq->size = size;
return seq;
seq = (asdl_int_seq *)PyArena_Malloc(arena, n);
if (!seq) {
PyErr_NoMemory();
return NULL;
}
memset(seq, 0, n);
seq->size = size;
return seq;
}

View file

@ -10,41 +10,41 @@
double atof(char *s)
{
double a = 0.0;
int e = 0;
int c;
while ((c = *s++) != '\0' && isdigit(c)) {
a = a*10.0 + (c - '0');
}
if (c == '.') {
while ((c = *s++) != '\0' && isdigit(c)) {
a = a*10.0 + (c - '0');
e = e-1;
}
}
if (c == 'e' || c == 'E') {
int sign = 1;
int i = 0;
c = *s++;
if (c == '+')
c = *s++;
else if (c == '-') {
c = *s++;
sign = -1;
}
while (isdigit(c)) {
i = i*10 + (c - '0');
c = *s++;
}
e += i*sign;
}
while (e > 0) {
a *= 10.0;
e--;
}
while (e < 0) {
a *= 0.1;
e++;
}
return a;
double a = 0.0;
int e = 0;
int c;
while ((c = *s++) != '\0' && isdigit(c)) {
a = a*10.0 + (c - '0');
}
if (c == '.') {
while ((c = *s++) != '\0' && isdigit(c)) {
a = a*10.0 + (c - '0');
e = e-1;
}
}
if (c == 'e' || c == 'E') {
int sign = 1;
int i = 0;
c = *s++;
if (c == '+')
c = *s++;
else if (c == '-') {
c = *s++;
sign = -1;
}
while (isdigit(c)) {
i = i*10 + (c - '0');
c = *s++;
}
e += i*sign;
}
while (e > 0) {
a *= 10.0;
e--;
}
while (e < 0) {
a *= 0.1;
e++;
}
return a;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,10 +4,10 @@
#include "Python.h"
#include "importdl.h"
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
#include <string.h> /* for strerror() */
#include <stdlib.h> /* for malloc(), free() */
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
#include <string.h> /* for strerror() */
#include <stdlib.h> /* for malloc(), free() */
#include <sys/ldr.h>
@ -22,85 +22,85 @@
extern char *Py_GetProgramName(void);
typedef struct Module {
struct Module *next;
void *entry;
struct Module *next;
void *entry;
} Module, *ModulePtr;
const struct filedescr _PyImport_DynLoadFiletab[] = {
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
};
static int
aix_getoldmodules(void **modlistptr)
{
register ModulePtr modptr, prevmodptr;
register struct ld_info *ldiptr;
register char *ldibuf;
register int errflag, bufsize = 1024;
register unsigned int offset;
char *progname = Py_GetProgramName();
/*
-- Get the list of loaded modules into ld_info structures.
*/
if ((ldibuf = malloc(bufsize)) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1
&& errno == ENOMEM) {
free(ldibuf);
bufsize += 1024;
if ((ldibuf = malloc(bufsize)) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
}
if (errflag == -1) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
/*
-- Make the modules list from the ld_info structures.
*/
ldiptr = (struct ld_info *)ldibuf;
prevmodptr = NULL;
do {
if (strstr(progname, ldiptr->ldinfo_filename) == NULL &&
strstr(ldiptr->ldinfo_filename, "python") == NULL) {
/*
-- Extract only the modules belonging to the main
-- executable + those containing "python" as a
-- substring (like the "python[version]" binary or
-- "libpython[version].a" in case it's a shared lib).
*/
offset = (unsigned int)ldiptr->ldinfo_next;
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
continue;
}
if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
while (*modlistptr) {
modptr = (ModulePtr)*modlistptr;
*modlistptr = (void *)modptr->next;
free(modptr);
}
return -1;
}
modptr->entry = ldiptr->ldinfo_dataorg;
modptr->next = NULL;
if (prevmodptr == NULL)
*modlistptr = (void *)modptr;
else
prevmodptr->next = modptr;
prevmodptr = modptr;
offset = (unsigned int)ldiptr->ldinfo_next;
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
} while (offset);
free(ldibuf);
return 0;
register ModulePtr modptr, prevmodptr;
register struct ld_info *ldiptr;
register char *ldibuf;
register int errflag, bufsize = 1024;
register unsigned int offset;
char *progname = Py_GetProgramName();
/*
-- Get the list of loaded modules into ld_info structures.
*/
if ((ldibuf = malloc(bufsize)) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
while ((errflag = loadquery(L_GETINFO, ldibuf, bufsize)) == -1
&& errno == ENOMEM) {
free(ldibuf);
bufsize += 1024;
if ((ldibuf = malloc(bufsize)) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
}
if (errflag == -1) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
return -1;
}
/*
-- Make the modules list from the ld_info structures.
*/
ldiptr = (struct ld_info *)ldibuf;
prevmodptr = NULL;
do {
if (strstr(progname, ldiptr->ldinfo_filename) == NULL &&
strstr(ldiptr->ldinfo_filename, "python") == NULL) {
/*
-- Extract only the modules belonging to the main
-- executable + those containing "python" as a
-- substring (like the "python[version]" binary or
-- "libpython[version].a" in case it's a shared lib).
*/
offset = (unsigned int)ldiptr->ldinfo_next;
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
continue;
}
if ((modptr = (ModulePtr)malloc(sizeof(Module))) == NULL) {
PyErr_SetString(PyExc_ImportError, strerror(errno));
while (*modlistptr) {
modptr = (ModulePtr)*modlistptr;
*modlistptr = (void *)modptr->next;
free(modptr);
}
return -1;
}
modptr->entry = ldiptr->ldinfo_dataorg;
modptr->next = NULL;
if (prevmodptr == NULL)
*modlistptr = (void *)modptr;
else
prevmodptr->next = modptr;
prevmodptr = modptr;
offset = (unsigned int)ldiptr->ldinfo_next;
ldiptr = (struct ld_info *)((char*)ldiptr + offset);
} while (offset);
free(ldibuf);
return 0;
}
@ -108,76 +108,76 @@ static void
aix_loaderror(const char *pathname)
{
char *message[1024], errbuf[1024];
register int i,j;
char *message[1024], errbuf[1024];
register int i,j;
struct errtab {
int errNo;
char *errstr;
} load_errtab[] = {
{L_ERROR_TOOMANY, "too many errors, rest skipped."},
{L_ERROR_NOLIB, "can't load library:"},
{L_ERROR_UNDEF, "can't find symbol in library:"},
{L_ERROR_RLDBAD,
"RLD index out of range or bad relocation type:"},
{L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
{L_ERROR_MEMBER,
"file not an archive or does not contain requested member:"},
{L_ERROR_TYPE, "symbol table mismatch:"},
{L_ERROR_ALIGN, "text alignment in file is wrong."},
{L_ERROR_SYSTEM, "System error:"},
{L_ERROR_ERRNO, NULL}
};
struct errtab {
int errNo;
char *errstr;
} load_errtab[] = {
{L_ERROR_TOOMANY, "too many errors, rest skipped."},
{L_ERROR_NOLIB, "can't load library:"},
{L_ERROR_UNDEF, "can't find symbol in library:"},
{L_ERROR_RLDBAD,
"RLD index out of range or bad relocation type:"},
{L_ERROR_FORMAT, "not a valid, executable xcoff file:"},
{L_ERROR_MEMBER,
"file not an archive or does not contain requested member:"},
{L_ERROR_TYPE, "symbol table mismatch:"},
{L_ERROR_ALIGN, "text alignment in file is wrong."},
{L_ERROR_SYSTEM, "System error:"},
{L_ERROR_ERRNO, NULL}
};
#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname);
PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname);
if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) {
ERRBUF_APPEND(strerror(errno));
ERRBUF_APPEND("\n");
}
for(i = 0; message[i] && *message[i]; i++) {
int nerr = atoi(message[i]);
for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
if (nerr == load_errtab[j].errNo && load_errtab[j].errstr)
ERRBUF_APPEND(load_errtab[j].errstr);
}
while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ;
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n");
}
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
PyErr_SetString(PyExc_ImportError, errbuf);
return;
if (!loadquery(L_GETMESSAGES, &message[0], sizeof(message))) {
ERRBUF_APPEND(strerror(errno));
ERRBUF_APPEND("\n");
}
for(i = 0; message[i] && *message[i]; i++) {
int nerr = atoi(message[i]);
for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
if (nerr == load_errtab[j].errNo && load_errtab[j].errstr)
ERRBUF_APPEND(load_errtab[j].errstr);
}
while (isdigit(Py_CHARMASK(*message[i]))) message[i]++ ;
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n");
}
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
PyErr_SetString(PyExc_ImportError, errbuf);
return;
}
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p;
dl_funcptr p;
/*
-- Invoke load() with L_NOAUTODEFER leaving the imported symbols
-- of the shared module unresolved. Thus we have to resolve them
-- explicitly with loadbind. The new module is loaded, then we
-- resolve its symbols using the list of already loaded modules
-- (only those that belong to the python executable). Get these
-- with loadquery(L_GETINFO).
*/
/*
-- Invoke load() with L_NOAUTODEFER leaving the imported symbols
-- of the shared module unresolved. Thus we have to resolve them
-- explicitly with loadbind. The new module is loaded, then we
-- resolve its symbols using the list of already loaded modules
-- (only those that belong to the python executable). Get these
-- with loadquery(L_GETINFO).
*/
static void *staticmodlistptr = NULL;
static void *staticmodlistptr = NULL;
if (!staticmodlistptr)
if (aix_getoldmodules(&staticmodlistptr) == -1)
return NULL;
p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0);
if (p == NULL) {
aix_loaderror(pathname);
return NULL;
}
if (!staticmodlistptr)
if (aix_getoldmodules(&staticmodlistptr) == -1)
return NULL;
p = (dl_funcptr) aix_load((char *)pathname, L_NOAUTODEFER, 0);
if (p == NULL) {
aix_loaderror(pathname);
return NULL;
}
return p;
return p;
}

View file

@ -9,39 +9,39 @@
const struct filedescr _PyImport_DynLoadFiletab[] = {
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
};
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
void *p;
int lib;
char funcname[258];
void *p;
int lib;
char funcname[258];
if (Py_VerboseFlag)
printf("load_library %s\n", pathname);
if (Py_VerboseFlag)
printf("load_library %s\n", pathname);
lib = load_library(pathname, 0);
if (lib < 0) {
char buf[512];
if (Py_VerboseFlag)
perror(pathname);
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s: %.200s",
pathname, strerror(errno));
PyErr_SetString(PyExc_ImportError, buf);
return NULL;
}
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
if (Py_VerboseFlag)
printf("get_symbol_address %s\n", funcname);
if (get_symbol_address(lib, funcname, -1, &p) < 0) {
p = NULL;
if (Py_VerboseFlag)
perror(funcname);
}
lib = load_library(pathname, 0);
if (lib < 0) {
char buf[512];
if (Py_VerboseFlag)
perror(pathname);
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s: %.200s",
pathname, strerror(errno));
PyErr_SetString(PyExc_ImportError, buf);
return NULL;
}
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
if (Py_VerboseFlag)
printf("get_symbol_address %s\n", funcname);
if (get_symbol_address(lib, funcname, -1, &p) < 0) {
p = NULL;
if (Py_VerboseFlag)
perror(funcname);
}
return (dl_funcptr) p;
return (dl_funcptr) p;
}

View file

@ -9,9 +9,9 @@
#include "importdl.h"
const struct filedescr _PyImport_DynLoadFiletab[] = {
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
};
#if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
@ -52,13 +52,13 @@ static PyObject *beos_dyn_images = NULL;
*/
static void beos_nuke_dyn( PyObject *item )
{
status_t retval;
status_t retval;
if( item ) {
image_id id = (image_id)PyInt_AsLong( item );
retval = unload_add_on( id );
}
if( item ) {
image_id id = (image_id)PyInt_AsLong( item );
retval = unload_add_on( id );
}
}
/* atexit() handler that'll call unload_add_on() for every item in the
@ -66,31 +66,31 @@ static void beos_nuke_dyn( PyObject *item )
*/
static void beos_cleanup_dyn( void )
{
if( beos_dyn_images ) {
int idx;
int list_size;
PyObject *id_list;
if( beos_dyn_images ) {
int idx;
int list_size;
PyObject *id_list;
#ifdef WITH_THREAD
PyThread_acquire_lock( beos_dyn_lock, 1 );
PyThread_acquire_lock( beos_dyn_lock, 1 );
#endif
id_list = PyDict_Values( beos_dyn_images );
id_list = PyDict_Values( beos_dyn_images );
list_size = PyList_Size( id_list );
for( idx = 0; idx < list_size; idx++ ) {
PyObject *the_item;
the_item = PyList_GetItem( id_list, idx );
beos_nuke_dyn( the_item );
}
list_size = PyList_Size( id_list );
for( idx = 0; idx < list_size; idx++ ) {
PyObject *the_item;
PyDict_Clear( beos_dyn_images );
the_item = PyList_GetItem( id_list, idx );
beos_nuke_dyn( the_item );
}
PyDict_Clear( beos_dyn_images );
#ifdef WITH_THREAD
PyThread_free_lock( beos_dyn_lock );
PyThread_free_lock( beos_dyn_lock );
#endif
}
}
}
/*
@ -98,20 +98,20 @@ static void beos_cleanup_dyn( void )
*/
static void beos_init_dyn( void )
{
/* We're protected from a race condition here by the atomic init_count
* variable.
*/
static int32 init_count = 0;
int32 val;
/* We're protected from a race condition here by the atomic init_count
* variable.
*/
static int32 init_count = 0;
int32 val;
val = atomic_add( &init_count, 1 );
if( beos_dyn_images == NULL && val == 0 ) {
beos_dyn_images = PyDict_New();
val = atomic_add( &init_count, 1 );
if( beos_dyn_images == NULL && val == 0 ) {
beos_dyn_images = PyDict_New();
#ifdef WITH_THREAD
beos_dyn_lock = PyThread_allocate_lock();
beos_dyn_lock = PyThread_allocate_lock();
#endif
atexit( beos_cleanup_dyn );
}
atexit( beos_cleanup_dyn );
}
}
/*
@ -122,133 +122,133 @@ static void beos_init_dyn( void )
*/
static void beos_add_dyn( char *name, image_id id )
{
int retval;
PyObject *py_id;
int retval;
PyObject *py_id;
if( beos_dyn_images == NULL ) {
beos_init_dyn();
}
if( beos_dyn_images == NULL ) {
beos_init_dyn();
}
#ifdef WITH_THREAD
retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
#endif
/* If there's already an object with this key in the dictionary,
* we're doing a reload(), so let's nuke it.
*/
py_id = PyDict_GetItemString( beos_dyn_images, name );
if( py_id ) {
beos_nuke_dyn( py_id );
retval = PyDict_DelItemString( beos_dyn_images, name );
}
/* If there's already an object with this key in the dictionary,
* we're doing a reload(), so let's nuke it.
*/
py_id = PyDict_GetItemString( beos_dyn_images, name );
if( py_id ) {
beos_nuke_dyn( py_id );
retval = PyDict_DelItemString( beos_dyn_images, name );
}
py_id = PyInt_FromLong( (long)id );
if( py_id ) {
retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
}
py_id = PyInt_FromLong( (long)id );
if( py_id ) {
retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
}
#ifdef WITH_THREAD
PyThread_release_lock( beos_dyn_lock );
PyThread_release_lock( beos_dyn_lock );
#endif
}
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p;
image_id the_id;
status_t retval;
char fullpath[PATH_MAX];
char funcname[258];
dl_funcptr p;
image_id the_id;
status_t retval;
char fullpath[PATH_MAX];
char funcname[258];
if( Py_VerboseFlag ) {
printf( "load_add_on( %s )\n", pathname );
}
if( Py_VerboseFlag ) {
printf( "load_add_on( %s )\n", pathname );
}
/* Hmm, this old bug appears to have regenerated itself; if the
* path isn't absolute, load_add_on() will fail. Reported to Be
* April 21, 1998.
*/
if( pathname[0] != '/' ) {
(void)getcwd( fullpath, PATH_MAX );
(void)strncat( fullpath, "/", PATH_MAX );
(void)strncat( fullpath, pathname, PATH_MAX );
if( Py_VerboseFlag ) {
printf( "load_add_on( %s )\n", fullpath );
}
} else {
(void)strcpy( fullpath, pathname );
}
/* Hmm, this old bug appears to have regenerated itself; if the
* path isn't absolute, load_add_on() will fail. Reported to Be
* April 21, 1998.
*/
if( pathname[0] != '/' ) {
(void)getcwd( fullpath, PATH_MAX );
(void)strncat( fullpath, "/", PATH_MAX );
(void)strncat( fullpath, pathname, PATH_MAX );
the_id = load_add_on( fullpath );
if( the_id < B_NO_ERROR ) {
/* It's too bad load_add_on() doesn't set errno or something...
*/
char buff[256]; /* hate hard-coded string sizes... */
if( Py_VerboseFlag ) {
printf( "load_add_on( %s )\n", fullpath );
}
} else {
(void)strcpy( fullpath, pathname );
}
if( Py_VerboseFlag ) {
printf( "load_add_on( %s ) failed", fullpath );
}
the_id = load_add_on( fullpath );
if( the_id < B_NO_ERROR ) {
/* It's too bad load_add_on() doesn't set errno or something...
*/
char buff[256]; /* hate hard-coded string sizes... */
if( the_id == B_ERROR )
PyOS_snprintf( buff, sizeof(buff),
"BeOS: Failed to load %.200s",
fullpath );
else
PyOS_snprintf( buff, sizeof(buff),
"Unknown error loading %.200s",
fullpath );
if( Py_VerboseFlag ) {
printf( "load_add_on( %s ) failed", fullpath );
}
PyErr_SetString( PyExc_ImportError, buff );
return NULL;
}
if( the_id == B_ERROR )
PyOS_snprintf( buff, sizeof(buff),
"BeOS: Failed to load %.200s",
fullpath );
else
PyOS_snprintf( buff, sizeof(buff),
"Unknown error loading %.200s",
fullpath );
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
if( Py_VerboseFlag ) {
printf( "get_image_symbol( %s )\n", funcname );
}
PyErr_SetString( PyExc_ImportError, buff );
return NULL;
}
retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
if( retval != B_NO_ERROR || p == NULL ) {
/* That's bad, we can't find that symbol in the module...
*/
char buff[256]; /* hate hard-coded string sizes... */
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
if( Py_VerboseFlag ) {
printf( "get_image_symbol( %s )\n", funcname );
}
if( Py_VerboseFlag ) {
printf( "get_image_symbol( %s ) failed", funcname );
}
retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
if( retval != B_NO_ERROR || p == NULL ) {
/* That's bad, we can't find that symbol in the module...
*/
char buff[256]; /* hate hard-coded string sizes... */
switch( retval ) {
case B_BAD_IMAGE_ID:
PyOS_snprintf( buff, sizeof(buff),
"can't load init function for dynamic module: "
"Invalid image ID for %.180s", fullpath );
break;
case B_BAD_INDEX:
PyOS_snprintf( buff, sizeof(buff),
"can't load init function for dynamic module: "
"Bad index for %.180s", funcname );
break;
default:
PyOS_snprintf( buff, sizeof(buff),
"can't load init function for dynamic module: "
"Unknown error looking up %.180s", funcname );
break;
}
if( Py_VerboseFlag ) {
printf( "get_image_symbol( %s ) failed", funcname );
}
retval = unload_add_on( the_id );
switch( retval ) {
case B_BAD_IMAGE_ID:
PyOS_snprintf( buff, sizeof(buff),
"can't load init function for dynamic module: "
"Invalid image ID for %.180s", fullpath );
break;
case B_BAD_INDEX:
PyOS_snprintf( buff, sizeof(buff),
"can't load init function for dynamic module: "
"Bad index for %.180s", funcname );
break;
default:
PyOS_snprintf( buff, sizeof(buff),
"can't load init function for dynamic module: "
"Unknown error looking up %.180s", funcname );
break;
}
PyErr_SetString( PyExc_ImportError, buff );
return NULL;
}
retval = unload_add_on( the_id );
/* Save the module name and image ID for later so we can clean up
* gracefully.
*/
beos_add_dyn( fqname, the_id );
PyErr_SetString( PyExc_ImportError, buff );
return NULL;
}
return p;
/* Save the module name and image ID for later so we can clean up
* gracefully.
*/
beos_add_dyn( fqname, the_id );
return p;
}

View file

@ -14,45 +14,45 @@
#endif
const struct filedescr _PyImport_DynLoadFiletab[] = {
{SHLIB_EXT, "rb", C_EXTENSION},
{"module"SHLIB_EXT, "rb", C_EXTENSION},
{0, 0}
{SHLIB_EXT, "rb", C_EXTENSION},
{"module"SHLIB_EXT, "rb", C_EXTENSION},
{0, 0}
};
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p;
shl_t lib;
int flags;
char funcname[258];
dl_funcptr p;
shl_t lib;
int flags;
char funcname[258];
flags = BIND_FIRST | BIND_DEFERRED;
if (Py_VerboseFlag) {
flags = BIND_FIRST | BIND_IMMEDIATE |
BIND_NONFATAL | BIND_VERBOSE;
printf("shl_load %s\n",pathname);
}
lib = shl_load(pathname, flags, 0);
/* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */
if (lib == NULL) {
char buf[256];
if (Py_VerboseFlag)
perror(pathname);
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s",
pathname);
PyErr_SetString(PyExc_ImportError, buf);
return NULL;
}
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname);
if (Py_VerboseFlag)
printf("shl_findsym %s\n", funcname);
if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {
shl_unload(lib);
p = NULL;
}
if (p == NULL && Py_VerboseFlag)
perror(funcname);
flags = BIND_FIRST | BIND_DEFERRED;
if (Py_VerboseFlag) {
flags = BIND_FIRST | BIND_IMMEDIATE |
BIND_NONFATAL | BIND_VERBOSE;
printf("shl_load %s\n",pathname);
}
lib = shl_load(pathname, flags, 0);
/* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */
if (lib == NULL) {
char buf[256];
if (Py_VerboseFlag)
perror(pathname);
PyOS_snprintf(buf, sizeof(buf), "Failed to load %.200s",
pathname);
PyErr_SetString(PyExc_ImportError, buf);
return NULL;
}
PyOS_snprintf(funcname, sizeof(funcname), FUNCNAME_PATTERN, shortname);
if (Py_VerboseFlag)
printf("shl_findsym %s\n", funcname);
if (shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p) == -1) {
shl_unload(lib);
p = NULL;
}
if (p == NULL && Py_VerboseFlag)
perror(funcname);
return p;
return p;
}

View file

@ -9,9 +9,9 @@
#include <mach-o/dyld.h>
const struct filedescr _PyImport_DynLoadFiletab[] = {
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{0, 0}
};
/*
@ -29,86 +29,86 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR
#else
#define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \
NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE
#endif
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p = NULL;
char funcname[258];
NSObjectFileImageReturnCode rc;
NSObjectFileImage image;
NSModule newModule;
NSSymbol theSym;
const char *errString;
char errBuf[512];
dl_funcptr p = NULL;
char funcname[258];
NSObjectFileImageReturnCode rc;
NSObjectFileImage image;
NSModule newModule;
NSSymbol theSym;
const char *errString;
char errBuf[512];
PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);
PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname);
#ifdef USE_DYLD_GLOBAL_NAMESPACE
if (NSIsSymbolNameDefined(funcname)) {
theSym = NSLookupAndBindSymbol(funcname);
p = (dl_funcptr)NSAddressOfSymbol(theSym);
return p;
}
if (NSIsSymbolNameDefined(funcname)) {
theSym = NSLookupAndBindSymbol(funcname);
p = (dl_funcptr)NSAddressOfSymbol(theSym);
return p;
}
#endif
rc = NSCreateObjectFileImageFromFile(pathname, &image);
switch(rc) {
default:
case NSObjectFileImageFailure:
case NSObjectFileImageFormat:
/* for these a message is printed on stderr by dyld */
errString = "Can't create object file image";
break;
case NSObjectFileImageSuccess:
errString = NULL;
break;
case NSObjectFileImageInappropriateFile:
errString = "Inappropriate file type for dynamic loading";
break;
case NSObjectFileImageArch:
errString = "Wrong CPU type in object file";
break;
case NSObjectFileImageAccess:
errString = "Can't read object file (no access)";
break;
}
if (errString == NULL) {
newModule = NSLinkModule(image, pathname, LINKOPTIONS);
if (newModule == NULL) {
int errNo;
const char *fileName, *moreErrorStr;
NSLinkEditErrors c;
NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s",
fileName, moreErrorStr);
errString = errBuf;
}
}
if (errString != NULL) {
PyErr_SetString(PyExc_ImportError, errString);
return NULL;
}
rc = NSCreateObjectFileImageFromFile(pathname, &image);
switch(rc) {
default:
case NSObjectFileImageFailure:
case NSObjectFileImageFormat:
/* for these a message is printed on stderr by dyld */
errString = "Can't create object file image";
break;
case NSObjectFileImageSuccess:
errString = NULL;
break;
case NSObjectFileImageInappropriateFile:
errString = "Inappropriate file type for dynamic loading";
break;
case NSObjectFileImageArch:
errString = "Wrong CPU type in object file";
break;
case NSObjectFileImageAccess:
errString = "Can't read object file (no access)";
break;
}
if (errString == NULL) {
newModule = NSLinkModule(image, pathname, LINKOPTIONS);
if (newModule == NULL) {
int errNo;
const char *fileName, *moreErrorStr;
NSLinkEditErrors c;
NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr );
PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s",
fileName, moreErrorStr);
errString = errBuf;
}
}
if (errString != NULL) {
PyErr_SetString(PyExc_ImportError, errString);
return NULL;
}
#ifdef USE_DYLD_GLOBAL_NAMESPACE
if (!NSIsSymbolNameDefined(funcname)) {
/* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
PyErr_Format(PyExc_ImportError,
"Loaded module does not contain symbol %.200s",
funcname);
return NULL;
}
theSym = NSLookupAndBindSymbol(funcname);
if (!NSIsSymbolNameDefined(funcname)) {
/* UnlinkModule() isn't implemented in current versions, but calling it does no harm */
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
PyErr_Format(PyExc_ImportError,
"Loaded module does not contain symbol %.200s",
funcname);
return NULL;
}
theSym = NSLookupAndBindSymbol(funcname);
#else
theSym = NSLookupSymbolInModule(newModule, funcname);
if ( theSym == NULL ) {
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
PyErr_Format(PyExc_ImportError,
"Loaded module does not contain symbol %.200s",
funcname);
return NULL;
}
theSym = NSLookupSymbolInModule(newModule, funcname);
if ( theSym == NULL ) {
/* NSUnLinkModule(newModule, FALSE); removed: causes problems for ObjC code */
PyErr_Format(PyExc_ImportError,
"Loaded module does not contain symbol %.200s",
funcname);
return NULL;
}
#endif
p = (dl_funcptr)NSAddressOfSymbol(theSym);
return p;
p = (dl_funcptr)NSAddressOfSymbol(theSym);
return p;
}

View file

@ -10,37 +10,37 @@
const struct filedescr _PyImport_DynLoadFiletab[] = {
{".pyd", "rb", C_EXTENSION},
{".dll", "rb", C_EXTENSION},
{0, 0}
{".pyd", "rb", C_EXTENSION},
{".dll", "rb", C_EXTENSION},
{0, 0}
};
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p;
APIRET rc;
HMODULE hDLL;
char failreason[256];
char funcname[258];
dl_funcptr p;
APIRET rc;
HMODULE hDLL;
char failreason[256];
char funcname[258];
rc = DosLoadModule(failreason,
sizeof(failreason),
pathname,
&hDLL);
rc = DosLoadModule(failreason,
sizeof(failreason),
pathname,
&hDLL);
if (rc != NO_ERROR) {
char errBuf[256];
PyOS_snprintf(errBuf, sizeof(errBuf),
"DLL load failed, rc = %d: %.200s",
rc, failreason);
PyErr_SetString(PyExc_ImportError, errBuf);
return NULL;
}
if (rc != NO_ERROR) {
char errBuf[256];
PyOS_snprintf(errBuf, sizeof(errBuf),
"DLL load failed, rc = %d: %.200s",
rc, failreason);
PyErr_SetString(PyExc_ImportError, errBuf);
return NULL;
}
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
rc = DosQueryProcAddr(hDLL, 0L, funcname, &p);
if (rc != NO_ERROR)
p = NULL; /* Signify Failure to Acquire Entrypoint */
return p;
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
rc = DosQueryProcAddr(hDLL, 0L, funcname, &p);
if (rc != NO_ERROR)
p = NULL; /* Signify Failure to Acquire Entrypoint */
return p;
}

View file

@ -33,111 +33,111 @@
const struct filedescr _PyImport_DynLoadFiletab[] = {
#ifdef __CYGWIN__
{".dll", "rb", C_EXTENSION},
{"module.dll", "rb", C_EXTENSION},
{".dll", "rb", C_EXTENSION},
{"module.dll", "rb", C_EXTENSION},
#else
#if defined(PYOS_OS2) && defined(PYCC_GCC)
{".pyd", "rb", C_EXTENSION},
{".dll", "rb", C_EXTENSION},
{".pyd", "rb", C_EXTENSION},
{".dll", "rb", C_EXTENSION},
#else
#ifdef __VMS
{".exe", "rb", C_EXTENSION},
{".EXE", "rb", C_EXTENSION},
{"module.exe", "rb", C_EXTENSION},
{"MODULE.EXE", "rb", C_EXTENSION},
{".exe", "rb", C_EXTENSION},
{".EXE", "rb", C_EXTENSION},
{"module.exe", "rb", C_EXTENSION},
{"MODULE.EXE", "rb", C_EXTENSION},
#else
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
#endif
#endif
#endif
{0, 0}
{0, 0}
};
static struct {
dev_t dev;
dev_t dev;
#ifdef __VMS
ino_t ino[3];
ino_t ino[3];
#else
ino_t ino;
ino_t ino;
#endif
void *handle;
void *handle;
} handles[128];
static int nhandles = 0;
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p;
void *handle;
char funcname[258];
char pathbuf[260];
int dlopenflags=0;
dl_funcptr p;
void *handle;
char funcname[258];
char pathbuf[260];
int dlopenflags=0;
if (strchr(pathname, '/') == NULL) {
/* Prefix bare filename with "./" */
PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
pathname = pathbuf;
}
if (strchr(pathname, '/') == NULL) {
/* Prefix bare filename with "./" */
PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
pathname = pathbuf;
}
PyOS_snprintf(funcname, sizeof(funcname),
LEAD_UNDERSCORE "init%.200s", shortname);
PyOS_snprintf(funcname, sizeof(funcname),
LEAD_UNDERSCORE "init%.200s", shortname);
if (fp != NULL) {
int i;
struct stat statb;
fstat(fileno(fp), &statb);
for (i = 0; i < nhandles; i++) {
if (statb.st_dev == handles[i].dev &&
statb.st_ino == handles[i].ino) {
p = (dl_funcptr) dlsym(handles[i].handle,
funcname);
return p;
}
}
if (nhandles < 128) {
handles[nhandles].dev = statb.st_dev;
if (fp != NULL) {
int i;
struct stat statb;
fstat(fileno(fp), &statb);
for (i = 0; i < nhandles; i++) {
if (statb.st_dev == handles[i].dev &&
statb.st_ino == handles[i].ino) {
p = (dl_funcptr) dlsym(handles[i].handle,
funcname);
return p;
}
}
if (nhandles < 128) {
handles[nhandles].dev = statb.st_dev;
#ifdef __VMS
handles[nhandles].ino[0] = statb.st_ino[0];
handles[nhandles].ino[1] = statb.st_ino[1];
handles[nhandles].ino[2] = statb.st_ino[2];
handles[nhandles].ino[0] = statb.st_ino[0];
handles[nhandles].ino[1] = statb.st_ino[1];
handles[nhandles].ino[2] = statb.st_ino[2];
#else
handles[nhandles].ino = statb.st_ino;
handles[nhandles].ino = statb.st_ino;
#endif
}
}
}
}
#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
dlopenflags = PyThreadState_GET()->interp->dlopenflags;
dlopenflags = PyThreadState_GET()->interp->dlopenflags;
#endif
if (Py_VerboseFlag)
PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
dlopenflags);
if (Py_VerboseFlag)
PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
dlopenflags);
#ifdef __VMS
/* VMS currently don't allow a pathname, use a logical name instead */
/* Concatenate 'python_module_' and shortname */
/* so "import vms.bar" will use the logical python_module_bar */
/* As C module use only one name space this is probably not a */
/* important limitation */
PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
shortname);
pathname = pathbuf;
/* VMS currently don't allow a pathname, use a logical name instead */
/* Concatenate 'python_module_' and shortname */
/* so "import vms.bar" will use the logical python_module_bar */
/* As C module use only one name space this is probably not a */
/* important limitation */
PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
shortname);
pathname = pathbuf;
#endif
handle = dlopen(pathname, dlopenflags);
handle = dlopen(pathname, dlopenflags);
if (handle == NULL) {
const char *error = dlerror();
if (error == NULL)
error = "unknown dlopen() error";
PyErr_SetString(PyExc_ImportError, error);
return NULL;
}
if (fp != NULL && nhandles < 128)
handles[nhandles++].handle = handle;
p = (dl_funcptr) dlsym(handle, funcname);
return p;
if (handle == NULL) {
const char *error = dlerror();
if (error == NULL)
error = "unknown dlopen() error";
PyErr_SetString(PyExc_ImportError, error);
return NULL;
}
if (fp != NULL && nhandles < 128)
handles[nhandles++].handle = handle;
p = (dl_funcptr) dlsym(handle, funcname);
return p;
}

View file

@ -17,11 +17,11 @@ void _Py_DeactivateActCtx(ULONG_PTR cookie);
const struct filedescr _PyImport_DynLoadFiletab[] = {
#ifdef _DEBUG
{"_d.pyd", "rb", C_EXTENSION},
{"_d.pyd", "rb", C_EXTENSION},
#else
{".pyd", "rb", C_EXTENSION},
{".pyd", "rb", C_EXTENSION},
#endif
{0, 0}
{0, 0}
};
@ -29,18 +29,18 @@ const struct filedescr _PyImport_DynLoadFiletab[] = {
C RTL implementations */
static int strcasecmp (char *string1, char *string2)
{
int first, second;
{
int first, second;
do {
first = tolower(*string1);
second = tolower(*string2);
string1++;
string2++;
} while (first && first == second);
do {
first = tolower(*string1);
second = tolower(*string2);
string1++;
string2++;
} while (first && first == second);
return (first - second);
}
return (first - second);
}
/* Function to return the name of the "python" DLL that the supplied module
@ -66,209 +66,209 @@ static int strcasecmp (char *string1, char *string2)
static char *GetPythonImport (HINSTANCE hModule)
{
unsigned char *dllbase, *import_data, *import_name;
DWORD pe_offset, opt_offset;
WORD opt_magic;
int num_dict_off, import_off;
unsigned char *dllbase, *import_data, *import_name;
DWORD pe_offset, opt_offset;
WORD opt_magic;
int num_dict_off, import_off;
/* Safety check input */
if (hModule == NULL) {
return NULL;
}
/* Safety check input */
if (hModule == NULL) {
return NULL;
}
/* Module instance is also the base load address. First portion of
memory is the MS-DOS loader, which holds the offset to the PE
header (from the load base) at 0x3C */
dllbase = (unsigned char *)hModule;
pe_offset = DWORD_AT(dllbase + 0x3C);
/* Module instance is also the base load address. First portion of
memory is the MS-DOS loader, which holds the offset to the PE
header (from the load base) at 0x3C */
dllbase = (unsigned char *)hModule;
pe_offset = DWORD_AT(dllbase + 0x3C);
/* The PE signature must be "PE\0\0" */
if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
return NULL;
}
/* The PE signature must be "PE\0\0" */
if (memcmp(dllbase+pe_offset,"PE\0\0",4)) {
return NULL;
}
/* Following the PE signature is the standard COFF header (20
bytes) and then the optional header. The optional header starts
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
uses 64-bits for some fields). It might also be 0x107 for a ROM
image, but we don't process that here.
/* Following the PE signature is the standard COFF header (20
bytes) and then the optional header. The optional header starts
with a magic value of 0x10B for PE32 or 0x20B for PE32+ (PE32+
uses 64-bits for some fields). It might also be 0x107 for a ROM
image, but we don't process that here.
The optional header ends with a data dictionary that directly
points to certain types of data, among them the import entries
(in the second table entry). Based on the header type, we
determine offsets for the data dictionary count and the entry
within the dictionary pointing to the imports. */
The optional header ends with a data dictionary that directly
points to certain types of data, among them the import entries
(in the second table entry). Based on the header type, we
determine offsets for the data dictionary count and the entry
within the dictionary pointing to the imports. */
opt_offset = pe_offset + 4 + 20;
opt_magic = WORD_AT(dllbase+opt_offset);
if (opt_magic == 0x10B) {
/* PE32 */
num_dict_off = 92;
import_off = 104;
} else if (opt_magic == 0x20B) {
/* PE32+ */
num_dict_off = 108;
import_off = 120;
} else {
/* Unsupported */
return NULL;
}
opt_offset = pe_offset + 4 + 20;
opt_magic = WORD_AT(dllbase+opt_offset);
if (opt_magic == 0x10B) {
/* PE32 */
num_dict_off = 92;
import_off = 104;
} else if (opt_magic == 0x20B) {
/* PE32+ */
num_dict_off = 108;
import_off = 120;
} else {
/* Unsupported */
return NULL;
}
/* Now if an import table exists, offset to it and walk the list of
imports. The import table is an array (ending when an entry has
empty values) of structures (20 bytes each), which contains (at
offset 12) a relative address (to the module base) at which a
string constant holding the import name is located. */
/* Now if an import table exists, offset to it and walk the list of
imports. The import table is an array (ending when an entry has
empty values) of structures (20 bytes each), which contains (at
offset 12) a relative address (to the module base) at which a
string constant holding the import name is located. */
if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
/* We have at least 2 tables - the import table is the second
one. But still it may be that the table size is zero */
if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
return NULL;
import_data = dllbase + DWORD_AT(dllbase +
opt_offset +
import_off);
while (DWORD_AT(import_data)) {
import_name = dllbase + DWORD_AT(import_data+12);
if (strlen(import_name) >= 6 &&
!strncmp(import_name,"python",6)) {
char *pch;
if (DWORD_AT(dllbase + opt_offset + num_dict_off) >= 2) {
/* We have at least 2 tables - the import table is the second
one. But still it may be that the table size is zero */
if (0 == DWORD_AT(dllbase + opt_offset + import_off + sizeof(DWORD)))
return NULL;
import_data = dllbase + DWORD_AT(dllbase +
opt_offset +
import_off);
while (DWORD_AT(import_data)) {
import_name = dllbase + DWORD_AT(import_data+12);
if (strlen(import_name) >= 6 &&
!strncmp(import_name,"python",6)) {
char *pch;
/* Ensure python prefix is followed only
by numbers to the end of the basename */
pch = import_name + 6;
/* Ensure python prefix is followed only
by numbers to the end of the basename */
pch = import_name + 6;
#ifdef _DEBUG
while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
#else
while (*pch && *pch != '.') {
while (*pch && *pch != '.') {
#endif
if (*pch >= '0' && *pch <= '9') {
pch++;
} else {
pch = NULL;
break;
}
}
if (pch) {
/* Found it - return the name */
return import_name;
}
}
import_data += 20;
}
}
if (*pch >= '0' && *pch <= '9') {
pch++;
} else {
pch = NULL;
break;
}
}
return NULL;
if (pch) {
/* Found it - return the name */
return import_name;
}
}
import_data += 20;
}
}
return NULL;
}
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
const char *pathname, FILE *fp)
const char *pathname, FILE *fp)
{
dl_funcptr p;
char funcname[258], *import_python;
dl_funcptr p;
char funcname[258], *import_python;
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
{
HINSTANCE hDLL = NULL;
char pathbuf[260];
LPTSTR dummy;
unsigned int old_mode;
ULONG_PTR cookie = 0;
/* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. However, Windows95
can sometimes not work correctly unless the absolute
path is used. If GetFullPathName() fails, the LoadLibrary
will certainly fail too, so use its error code */
{
HINSTANCE hDLL = NULL;
char pathbuf[260];
LPTSTR dummy;
unsigned int old_mode;
ULONG_PTR cookie = 0;
/* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. However, Windows95
can sometimes not work correctly unless the absolute
path is used. If GetFullPathName() fails, the LoadLibrary
will certainly fail too, so use its error code */
/* Don't display a message box when Python can't load a DLL */
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
/* Don't display a message box when Python can't load a DLL */
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
if (GetFullPathName(pathname,
sizeof(pathbuf),
pathbuf,
&dummy)) {
ULONG_PTR cookie = _Py_ActivateActCtx();
/* XXX This call doesn't exist in Windows CE */
hDLL = LoadLibraryEx(pathname, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
_Py_DeactivateActCtx(cookie);
}
if (GetFullPathName(pathname,
sizeof(pathbuf),
pathbuf,
&dummy)) {
ULONG_PTR cookie = _Py_ActivateActCtx();
/* XXX This call doesn't exist in Windows CE */
hDLL = LoadLibraryEx(pathname, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
_Py_DeactivateActCtx(cookie);
}
/* restore old error mode settings */
SetErrorMode(old_mode);
/* restore old error mode settings */
SetErrorMode(old_mode);
if (hDLL==NULL){
char errBuf[256];
unsigned int errorCode;
if (hDLL==NULL){
char errBuf[256];
unsigned int errorCode;
/* Get an error string from Win32 error code */
char theInfo[256]; /* Pointer to error text
from system */
int theLength; /* Length of error text */
/* Get an error string from Win32 error code */
char theInfo[256]; /* Pointer to error text
from system */
int theLength; /* Length of error text */
errorCode = GetLastError();
errorCode = GetLastError();
theLength = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
NULL, /* message source */
errorCode, /* the message (error) ID */
0, /* default language environment */
(LPTSTR) theInfo, /* the buffer */
sizeof(theInfo), /* the buffer size */
NULL); /* no additional format args. */
theLength = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, /* flags */
NULL, /* message source */
errorCode, /* the message (error) ID */
0, /* default language environment */
(LPTSTR) theInfo, /* the buffer */
sizeof(theInfo), /* the buffer size */
NULL); /* no additional format args. */
/* Problem: could not get the error message.
This should not happen if called correctly. */
if (theLength == 0) {
PyOS_snprintf(errBuf, sizeof(errBuf),
"DLL load failed with error code %d",
errorCode);
} else {
size_t len;
/* For some reason a \r\n
is appended to the text */
if (theLength >= 2 &&
theInfo[theLength-2] == '\r' &&
theInfo[theLength-1] == '\n') {
theLength -= 2;
theInfo[theLength] = '\0';
}
strcpy(errBuf, "DLL load failed: ");
len = strlen(errBuf);
strncpy(errBuf+len, theInfo,
sizeof(errBuf)-len);
errBuf[sizeof(errBuf)-1] = '\0';
}
PyErr_SetString(PyExc_ImportError, errBuf);
return NULL;
} else {
char buffer[256];
/* Problem: could not get the error message.
This should not happen if called correctly. */
if (theLength == 0) {
PyOS_snprintf(errBuf, sizeof(errBuf),
"DLL load failed with error code %d",
errorCode);
} else {
size_t len;
/* For some reason a \r\n
is appended to the text */
if (theLength >= 2 &&
theInfo[theLength-2] == '\r' &&
theInfo[theLength-1] == '\n') {
theLength -= 2;
theInfo[theLength] = '\0';
}
strcpy(errBuf, "DLL load failed: ");
len = strlen(errBuf);
strncpy(errBuf+len, theInfo,
sizeof(errBuf)-len);
errBuf[sizeof(errBuf)-1] = '\0';
}
PyErr_SetString(PyExc_ImportError, errBuf);
return NULL;
} else {
char buffer[256];
#ifdef _DEBUG
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll",
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll",
#else
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll",
PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll",
#endif
PY_MAJOR_VERSION,PY_MINOR_VERSION);
import_python = GetPythonImport(hDLL);
PY_MAJOR_VERSION,PY_MINOR_VERSION);
import_python = GetPythonImport(hDLL);
if (import_python &&
strcasecmp(buffer,import_python)) {
PyOS_snprintf(buffer, sizeof(buffer),
"Module use of %.150s conflicts "
"with this version of Python.",
import_python);
PyErr_SetString(PyExc_ImportError,buffer);
FreeLibrary(hDLL);
return NULL;
}
}
p = GetProcAddress(hDLL, funcname);
}
if (import_python &&
strcasecmp(buffer,import_python)) {
PyOS_snprintf(buffer, sizeof(buffer),
"Module use of %.150s conflicts "
"with this version of Python.",
import_python);
PyErr_SetString(PyExc_ImportError,buffer);
FreeLibrary(hDLL);
return NULL;
}
}
p = GetProcAddress(hDLL, funcname);
}
return p;
return p;
}

File diff suppressed because it is too large Load diff

View file

@ -12,24 +12,24 @@
the appropriate bytes from M___main__.c. */
static unsigned char M___hello__[] = {
99,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,115,9,0,0,0,100,0,0,71,72,100,1,0,83,40,
2,0,0,0,115,14,0,0,0,72,101,108,108,111,32,119,
111,114,108,100,46,46,46,78,40,0,0,0,0,40,0,0,
0,0,40,0,0,0,0,40,0,0,0,0,115,8,0,0,
0,104,101,108,108,111,46,112,121,115,1,0,0,0,63,1,
0,0,0,115,0,0,0,0,
99,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
0,115,9,0,0,0,100,0,0,71,72,100,1,0,83,40,
2,0,0,0,115,14,0,0,0,72,101,108,108,111,32,119,
111,114,108,100,46,46,46,78,40,0,0,0,0,40,0,0,
0,0,40,0,0,0,0,40,0,0,0,0,115,8,0,0,
0,104,101,108,108,111,46,112,121,115,1,0,0,0,63,1,
0,0,0,115,0,0,0,0,
};
#define SIZE (int)sizeof(M___hello__)
static struct _frozen _PyImport_FrozenModules[] = {
/* Test module */
{"__hello__", M___hello__, SIZE},
/* Test package (negative size indicates package-ness) */
{"__phello__", M___hello__, -SIZE},
{"__phello__.spam", M___hello__, SIZE},
{0, 0, 0} /* sentinel */
/* Test module */
{"__hello__", M___hello__, SIZE},
/* Test package (negative size indicates package-ness) */
{"__phello__", M___hello__, -SIZE},
{"__phello__.spam", M___hello__, SIZE},
{0, 0, 0} /* sentinel */
};
/* Embedding apps may change this pointer to point to their favorite

View file

@ -14,55 +14,55 @@ extern int PyInitFrozenExtensions(void);
int
Py_FrozenMain(int argc, char **argv)
{
char *p;
int n, sts;
int inspect = 0;
int unbuffered = 0;
char *p;
int n, sts;
int inspect = 0;
int unbuffered = 0;
Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
inspect = 1;
if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
unbuffered = 1;
if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
inspect = 1;
if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
unbuffered = 1;
if (unbuffered) {
setbuf(stdin, (char *)NULL);
setbuf(stdout, (char *)NULL);
setbuf(stderr, (char *)NULL);
}
if (unbuffered) {
setbuf(stdin, (char *)NULL);
setbuf(stdout, (char *)NULL);
setbuf(stderr, (char *)NULL);
}
#ifdef MS_WINDOWS
PyInitFrozenExtensions();
PyInitFrozenExtensions();
#endif /* MS_WINDOWS */
Py_SetProgramName(argv[0]);
Py_Initialize();
Py_SetProgramName(argv[0]);
Py_Initialize();
#ifdef MS_WINDOWS
PyWinFreeze_ExeInit();
PyWinFreeze_ExeInit();
#endif
if (Py_VerboseFlag)
fprintf(stderr, "Python %s\n%s\n",
Py_GetVersion(), Py_GetCopyright());
if (Py_VerboseFlag)
fprintf(stderr, "Python %s\n%s\n",
Py_GetVersion(), Py_GetCopyright());
PySys_SetArgv(argc, argv);
PySys_SetArgv(argc, argv);
n = PyImport_ImportFrozenModule("__main__");
if (n == 0)
Py_FatalError("__main__ not frozen");
if (n < 0) {
PyErr_Print();
sts = 1;
}
else
sts = 0;
n = PyImport_ImportFrozenModule("__main__");
if (n == 0)
Py_FatalError("__main__ not frozen");
if (n < 0) {
PyErr_Print();
sts = 1;
}
else
sts = 0;
if (inspect && isatty((int)fileno(stdin)))
sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
if (inspect && isatty((int)fileno(stdin)))
sts = PyRun_AnyFile(stdin, "<stdin>") != 0;
#ifdef MS_WINDOWS
PyWinFreeze_ExeTerm();
PyWinFreeze_ExeTerm();
#endif
Py_Finalize();
return sts;
Py_Finalize();
return sts;
}

View file

@ -12,129 +12,129 @@
static int
future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename)
{
int i;
asdl_seq *names;
int i;
asdl_seq *names;
assert(s->kind == ImportFrom_kind);
assert(s->kind == ImportFrom_kind);
names = s->v.ImportFrom.names;
for (i = 0; i < asdl_seq_LEN(names); i++) {
alias_ty name = (alias_ty)asdl_seq_GET(names, i);
const char *feature = PyString_AsString(name->name);
if (!feature)
return 0;
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
continue;
} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
continue;
} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
ff->ff_features |= CO_FUTURE_DIVISION;
} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
ff->ff_features |= CO_FUTURE_PRINT_FUNCTION;
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
ff->ff_features |= CO_FUTURE_UNICODE_LITERALS;
} else if (strcmp(feature, "braces") == 0) {
PyErr_SetString(PyExc_SyntaxError,
"not a chance");
PyErr_SyntaxLocation(filename, s->lineno);
return 0;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
PyErr_SyntaxLocation(filename, s->lineno);
return 0;
}
}
return 1;
names = s->v.ImportFrom.names;
for (i = 0; i < asdl_seq_LEN(names); i++) {
alias_ty name = (alias_ty)asdl_seq_GET(names, i);
const char *feature = PyString_AsString(name->name);
if (!feature)
return 0;
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
continue;
} else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
continue;
} else if (strcmp(feature, FUTURE_DIVISION) == 0) {
ff->ff_features |= CO_FUTURE_DIVISION;
} else if (strcmp(feature, FUTURE_ABSOLUTE_IMPORT) == 0) {
ff->ff_features |= CO_FUTURE_ABSOLUTE_IMPORT;
} else if (strcmp(feature, FUTURE_WITH_STATEMENT) == 0) {
ff->ff_features |= CO_FUTURE_WITH_STATEMENT;
} else if (strcmp(feature, FUTURE_PRINT_FUNCTION) == 0) {
ff->ff_features |= CO_FUTURE_PRINT_FUNCTION;
} else if (strcmp(feature, FUTURE_UNICODE_LITERALS) == 0) {
ff->ff_features |= CO_FUTURE_UNICODE_LITERALS;
} else if (strcmp(feature, "braces") == 0) {
PyErr_SetString(PyExc_SyntaxError,
"not a chance");
PyErr_SyntaxLocation(filename, s->lineno);
return 0;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
PyErr_SyntaxLocation(filename, s->lineno);
return 0;
}
}
return 1;
}
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
{
int i, found_docstring = 0, done = 0, prev_line = 0;
int i, found_docstring = 0, done = 0, prev_line = 0;
static PyObject *future;
if (!future) {
future = PyString_InternFromString("__future__");
if (!future)
return 0;
}
static PyObject *future;
if (!future) {
future = PyString_InternFromString("__future__");
if (!future)
return 0;
}
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
return 1;
if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
return 1;
/* A subsequent pass will detect future imports that don't
appear at the beginning of the file. There's one case,
however, that is easier to handle here: A series of imports
joined by semi-colons, where the first import is a future
statement but some subsequent import has the future form
but is preceded by a regular import.
*/
/* A subsequent pass will detect future imports that don't
appear at the beginning of the file. There's one case,
however, that is easier to handle here: A series of imports
joined by semi-colons, where the first import is a future
statement but some subsequent import has the future form
but is preceded by a regular import.
*/
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
if (done && s->lineno > prev_line)
return 1;
prev_line = s->lineno;
for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);
/* The tests below will return from this function unless it is
still possible to find a future statement. The only things
that can precede a future statement are another future
statement and a doc string.
*/
if (done && s->lineno > prev_line)
return 1;
prev_line = s->lineno;
if (s->kind == ImportFrom_kind) {
if (s->v.ImportFrom.module == future) {
if (done) {
PyErr_SetString(PyExc_SyntaxError,
ERR_LATE_FUTURE);
PyErr_SyntaxLocation(filename,
s->lineno);
return 0;
}
if (!future_check_features(ff, s, filename))
return 0;
ff->ff_lineno = s->lineno;
}
else
done = 1;
}
else if (s->kind == Expr_kind && !found_docstring) {
expr_ty e = s->v.Expr.value;
if (e->kind != Str_kind)
done = 1;
else
found_docstring = 1;
}
else
done = 1;
}
return 1;
/* The tests below will return from this function unless it is
still possible to find a future statement. The only things
that can precede a future statement are another future
statement and a doc string.
*/
if (s->kind == ImportFrom_kind) {
if (s->v.ImportFrom.module == future) {
if (done) {
PyErr_SetString(PyExc_SyntaxError,
ERR_LATE_FUTURE);
PyErr_SyntaxLocation(filename,
s->lineno);
return 0;
}
if (!future_check_features(ff, s, filename))
return 0;
ff->ff_lineno = s->lineno;
}
else
done = 1;
}
else if (s->kind == Expr_kind && !found_docstring) {
expr_ty e = s->v.Expr.value;
if (e->kind != Str_kind)
done = 1;
else
found_docstring = 1;
}
else
done = 1;
}
return 1;
}
PyFutureFeatures *
PyFuture_FromAST(mod_ty mod, const char *filename)
{
PyFutureFeatures *ff;
PyFutureFeatures *ff;
ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
if (ff == NULL) {
PyErr_NoMemory();
return NULL;
}
ff->ff_features = 0;
ff->ff_lineno = -1;
ff = (PyFutureFeatures *)PyObject_Malloc(sizeof(PyFutureFeatures));
if (ff == NULL) {
PyErr_NoMemory();
return NULL;
}
ff->ff_features = 0;
ff->ff_lineno = -1;
if (!future_parse(ff, mod, filename)) {
PyObject_Free(ff);
return NULL;
}
return ff;
if (!future_parse(ff, mod, filename)) {
PyObject_Free(ff);
return NULL;
}
return ff;
}

File diff suppressed because it is too large Load diff

View file

@ -26,24 +26,24 @@ extern char *getwd(char *);
char *
getcwd(char *buf, int size)
{
char localbuf[MAXPATHLEN+1];
char *ret;
if (size <= 0) {
errno = EINVAL;
return NULL;
}
ret = getwd(localbuf);
if (ret != NULL && strlen(localbuf) >= (size_t)size) {
errno = ERANGE;
return NULL;
}
if (ret == NULL) {
errno = EACCES; /* Most likely error */
return NULL;
}
strncpy(buf, localbuf, size);
return buf;
char localbuf[MAXPATHLEN+1];
char *ret;
if (size <= 0) {
errno = EINVAL;
return NULL;
}
ret = getwd(localbuf);
if (ret != NULL && strlen(localbuf) >= (size_t)size) {
errno = ERANGE;
return NULL;
}
if (ret == NULL) {
errno = EACCES; /* Most likely error */
return NULL;
}
strncpy(buf, localbuf, size);
return buf;
}
#else /* !HAVE_GETWD */
@ -57,27 +57,27 @@ getcwd(char *buf, int size)
char *
getcwd(char *buf, int size)
{
FILE *fp;
char *p;
int sts;
if (size <= 0) {
errno = EINVAL;
return NULL;
}
if ((fp = popen(PWD_CMD, "r")) == NULL)
return NULL;
if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) {
errno = EACCES; /* Most likely error */
return NULL;
}
for (p = buf; *p != '\n'; p++) {
if (*p == '\0') {
errno = ERANGE;
return NULL;
}
}
*p = '\0';
return buf;
FILE *fp;
char *p;
int sts;
if (size <= 0) {
errno = EINVAL;
return NULL;
}
if ((fp = popen(PWD_CMD, "r")) == NULL)
return NULL;
if (fgets(buf, size, fp) == NULL || (sts = pclose(fp)) != 0) {
errno = EACCES; /* Most likely error */
return NULL;
}
for (p = buf; *p != '\n'; p++) {
if (*p == '\0') {
errno = ERANGE;
return NULL;
}
}
*p = '\0';
return buf;
}
#endif /* !HAVE_GETWD */

View file

@ -7,8 +7,8 @@
*
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* 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, this permission notice and
* the following disclaimer notice appear unmodified in all copies.
*
@ -40,84 +40,84 @@ char *_PyOS_optarg = NULL; /* optional argument */
int _PyOS_GetOpt(int argc, char **argv, char *optstring)
{
static char *opt_ptr = "";
char *ptr;
int option;
static char *opt_ptr = "";
char *ptr;
int option;
if (*opt_ptr == '\0') {
if (*opt_ptr == '\0') {
if (_PyOS_optind >= argc)
return -1;
if (_PyOS_optind >= argc)
return -1;
#ifdef MS_WINDOWS
else if (strcmp(argv[_PyOS_optind], "/?") == 0) {
++_PyOS_optind;
return 'h';
}
else if (strcmp(argv[_PyOS_optind], "/?") == 0) {
++_PyOS_optind;
return 'h';
}
#endif
else if (argv[_PyOS_optind][0] != '-' ||
argv[_PyOS_optind][1] == '\0' /* lone dash */ )
return -1;
else if (argv[_PyOS_optind][0] != '-' ||
argv[_PyOS_optind][1] == '\0' /* lone dash */ )
return -1;
else if (strcmp(argv[_PyOS_optind], "--") == 0) {
++_PyOS_optind;
return -1;
}
else if (strcmp(argv[_PyOS_optind], "--") == 0) {
++_PyOS_optind;
return -1;
}
else if (strcmp(argv[_PyOS_optind], "--help") == 0) {
++_PyOS_optind;
return 'h';
}
else if (strcmp(argv[_PyOS_optind], "--help") == 0) {
++_PyOS_optind;
return 'h';
}
else if (strcmp(argv[_PyOS_optind], "--version") == 0) {
++_PyOS_optind;
return 'V';
}
else if (strcmp(argv[_PyOS_optind], "--version") == 0) {
++_PyOS_optind;
return 'V';
}
opt_ptr = &argv[_PyOS_optind++][1];
}
opt_ptr = &argv[_PyOS_optind++][1];
}
if ( (option = *opt_ptr++) == '\0')
return -1;
if ( (option = *opt_ptr++) == '\0')
return -1;
if (option == 'J') {
fprintf(stderr, "-J is reserved for Jython\n");
return '_';
}
if (option == 'J') {
fprintf(stderr, "-J is reserved for Jython\n");
return '_';
}
if (option == 'X') {
fprintf(stderr,
"-X is reserved for implementation-specific arguments\n");
return '_';
}
if (option == 'X') {
fprintf(stderr,
"-X is reserved for implementation-specific arguments\n");
return '_';
}
if ((ptr = strchr(optstring, option)) == NULL) {
if (_PyOS_opterr)
fprintf(stderr, "Unknown option: -%c\n", option);
if ((ptr = strchr(optstring, option)) == NULL) {
if (_PyOS_opterr)
fprintf(stderr, "Unknown option: -%c\n", option);
return '_';
}
return '_';
}
if (*(ptr + 1) == ':') {
if (*opt_ptr != '\0') {
_PyOS_optarg = opt_ptr;
opt_ptr = "";
}
if (*(ptr + 1) == ':') {
if (*opt_ptr != '\0') {
_PyOS_optarg = opt_ptr;
opt_ptr = "";
}
else {
if (_PyOS_optind >= argc) {
if (_PyOS_opterr)
fprintf(stderr,
"Argument expected for the -%c option\n", option);
return '_';
}
else {
if (_PyOS_optind >= argc) {
if (_PyOS_opterr)
fprintf(stderr,
"Argument expected for the -%c option\n", option);
return '_';
}
_PyOS_optarg = argv[_PyOS_optind++];
}
}
_PyOS_optarg = argv[_PyOS_optind++];
}
}
return option;
return option;
}
#ifdef __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -13,66 +13,66 @@
#include "importdl.h"
extern dl_funcptr _PyImport_GetDynLoadFunc(const char *name,
const char *shortname,
const char *pathname, FILE *fp);
const char *shortname,
const char *pathname, FILE *fp);
PyObject *
_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp)
{
PyObject *m;
char *lastdot, *shortname, *packagecontext, *oldcontext;
dl_funcptr p;
PyObject *m;
char *lastdot, *shortname, *packagecontext, *oldcontext;
dl_funcptr p;
if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
Py_INCREF(m);
return m;
}
lastdot = strrchr(name, '.');
if (lastdot == NULL) {
packagecontext = NULL;
shortname = name;
}
else {
packagecontext = name;
shortname = lastdot+1;
}
if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
Py_INCREF(m);
return m;
}
lastdot = strrchr(name, '.');
if (lastdot == NULL) {
packagecontext = NULL;
shortname = name;
}
else {
packagecontext = name;
shortname = lastdot+1;
}
p = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp);
if (PyErr_Occurred())
return NULL;
if (p == NULL) {
PyErr_Format(PyExc_ImportError,
"dynamic module does not define init function (init%.200s)",
shortname);
return NULL;
}
oldcontext = _Py_PackageContext;
_Py_PackageContext = packagecontext;
(*p)();
_Py_PackageContext = oldcontext;
if (PyErr_Occurred())
return NULL;
p = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp);
if (PyErr_Occurred())
return NULL;
if (p == NULL) {
PyErr_Format(PyExc_ImportError,
"dynamic module does not define init function (init%.200s)",
shortname);
return NULL;
}
oldcontext = _Py_PackageContext;
_Py_PackageContext = packagecontext;
(*p)();
_Py_PackageContext = oldcontext;
if (PyErr_Occurred())
return NULL;
m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
if (m == NULL) {
PyErr_SetString(PyExc_SystemError,
"dynamic module not initialized properly");
return NULL;
}
/* Remember the filename as the __file__ attribute */
if (PyModule_AddStringConstant(m, "__file__", pathname) < 0)
PyErr_Clear(); /* Not important enough to report */
m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
if (m == NULL) {
PyErr_SetString(PyExc_SystemError,
"dynamic module not initialized properly");
return NULL;
}
/* Remember the filename as the __file__ attribute */
if (PyModule_AddStringConstant(m, "__file__", pathname) < 0)
PyErr_Clear(); /* Not important enough to report */
if (_PyImport_FixupExtension(name, pathname) == NULL)
return NULL;
if (Py_VerboseFlag)
PySys_WriteStderr(
"import %s # dynamically loaded from %s\n",
name, pathname);
Py_INCREF(m);
return m;
if (_PyImport_FixupExtension(name, pathname) == NULL)
return NULL;
if (Py_VerboseFlag)
PySys_WriteStderr(
"import %s # dynamically loaded from %s\n",
name, pathname);
Py_INCREF(m);
return m;
}
#endif /* HAVE_DYNAMIC_LOADING */

View file

@ -8,28 +8,28 @@ extern "C" {
/* Definitions for dynamic loading of extension modules */
enum filetype {
SEARCH_ERROR,
PY_SOURCE,
PY_COMPILED,
C_EXTENSION,
PY_RESOURCE, /* Mac only */
PKG_DIRECTORY,
C_BUILTIN,
PY_FROZEN,
PY_CODERESOURCE, /* Mac only */
IMP_HOOK
SEARCH_ERROR,
PY_SOURCE,
PY_COMPILED,
C_EXTENSION,
PY_RESOURCE, /* Mac only */
PKG_DIRECTORY,
C_BUILTIN,
PY_FROZEN,
PY_CODERESOURCE, /* Mac only */
IMP_HOOK
};
struct filedescr {
char *suffix;
char *mode;
enum filetype type;
char *suffix;
char *mode;
enum filetype type;
};
extern struct filedescr * _PyImport_Filetab;
extern const struct filedescr _PyImport_DynLoadFiletab[];
extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname,
FILE *);
FILE *);
/* Max length of module suffix searched for -- accommodates "module.slb" */
#define MAXSUFFIXSIZE 12

View file

@ -4,10 +4,10 @@ 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,
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
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.
@ -25,45 +25,45 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "Python.h"
#include "pymactoolbox.h"
#include <arpa/inet.h> /* for ntohl, htonl */
#include <arpa/inet.h> /* for ntohl, htonl */
/* Like strerror() but for Mac OS error numbers */
char *
PyMac_StrError(int err)
{
static char buf[256];
PyObject *m;
PyObject *rv;
static char buf[256];
PyObject *m;
PyObject *rv;
m = PyImport_ImportModuleNoBlock("MacOS");
if (!m) {
if (Py_VerboseFlag)
PyErr_Print();
PyErr_Clear();
rv = NULL;
}
else {
rv = PyObject_CallMethod(m, "GetErrorString", "i", err);
if (!rv)
PyErr_Clear();
}
if (!rv) {
buf[0] = '\0';
}
else {
char *input = PyString_AsString(rv);
if (!input) {
PyErr_Clear();
buf[0] = '\0';
} else {
strncpy(buf, input, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
}
Py_DECREF(rv);
}
Py_XDECREF(m);
return buf;
m = PyImport_ImportModuleNoBlock("MacOS");
if (!m) {
if (Py_VerboseFlag)
PyErr_Print();
PyErr_Clear();
rv = NULL;
}
else {
rv = PyObject_CallMethod(m, "GetErrorString", "i", err);
if (!rv)
PyErr_Clear();
}
if (!rv) {
buf[0] = '\0';
}
else {
char *input = PyString_AsString(rv);
if (!input) {
PyErr_Clear();
buf[0] = '\0';
} else {
strncpy(buf, input, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
}
Py_DECREF(rv);
}
Py_XDECREF(m);
return buf;
}
/* Exception object shared by all Mac specific modules for Mac OS errors */
@ -73,36 +73,36 @@ PyObject *PyMac_OSErrException;
PyObject *
PyMac_GetOSErrException(void)
{
if (PyMac_OSErrException == NULL)
PyMac_OSErrException = PyErr_NewException("MacOS.Error", NULL, NULL);
return PyMac_OSErrException;
if (PyMac_OSErrException == NULL)
PyMac_OSErrException = PyErr_NewException("MacOS.Error", NULL, NULL);
return PyMac_OSErrException;
}
/* Set a MAC-specific error from errno, and return NULL; return None if no error */
PyObject *
PyObject *
PyErr_Mac(PyObject *eobj, int err)
{
char *msg;
PyObject *v;
if (err == 0 && !PyErr_Occurred()) {
Py_INCREF(Py_None);
return Py_None;
}
if (err == -1 && PyErr_Occurred())
return NULL;
msg = PyMac_StrError(err);
v = Py_BuildValue("(is)", err, msg);
PyErr_SetObject(eobj, v);
Py_DECREF(v);
return NULL;
char *msg;
PyObject *v;
if (err == 0 && !PyErr_Occurred()) {
Py_INCREF(Py_None);
return Py_None;
}
if (err == -1 && PyErr_Occurred())
return NULL;
msg = PyMac_StrError(err);
v = Py_BuildValue("(is)", err, msg);
PyErr_SetObject(eobj, v);
Py_DECREF(v);
return NULL;
}
/* Call PyErr_Mac with PyMac_OSErrException */
PyObject *
PyMac_Error(OSErr err)
{
return PyErr_Mac(PyMac_GetOSErrException(), err);
return PyErr_Mac(PyMac_GetOSErrException(), err);
}
@ -110,49 +110,49 @@ PyMac_Error(OSErr err)
OSErr
PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
{
PyObject *fs, *exc;
PyObject *rv = NULL;
char *input;
OSErr err = noErr;
PyObject *fs, *exc;
PyObject *rv = NULL;
char *input;
OSErr err = noErr;
*path = '\0';
*path = '\0';
fs = PyMac_BuildFSSpec(fss);
if (!fs)
goto error;
fs = PyMac_BuildFSSpec(fss);
if (!fs)
goto error;
rv = PyObject_CallMethod(fs, "as_pathname", "");
if (!rv)
goto error;
rv = PyObject_CallMethod(fs, "as_pathname", "");
if (!rv)
goto error;
input = PyString_AsString(rv);
if (!input)
goto error;
input = PyString_AsString(rv);
if (!input)
goto error;
strncpy(path, input, len - 1);
path[len - 1] = '\0';
strncpy(path, input, len - 1);
path[len - 1] = '\0';
Py_XDECREF(rv);
Py_XDECREF(fs);
return err;
Py_XDECREF(rv);
Py_XDECREF(fs);
return err;
error:
exc = PyErr_Occurred();
if (exc && PyErr_GivenExceptionMatches(exc,
PyMac_GetOSErrException())) {
PyObject *args = PyObject_GetAttrString(exc, "args");
if (args) {
char *ignore;
PyArg_ParseTuple(args, "is", &err, &ignore);
Py_XDECREF(args);
}
}
if (err == noErr)
err = -1;
PyErr_Clear();
Py_XDECREF(rv);
Py_XDECREF(fs);
return err;
exc = PyErr_Occurred();
if (exc && PyErr_GivenExceptionMatches(exc,
PyMac_GetOSErrException())) {
PyObject *args = PyObject_GetAttrString(exc, "args");
if (args) {
char *ignore;
PyArg_ParseTuple(args, "is", &err, &ignore);
Py_XDECREF(args);
}
}
if (err == noErr)
err = -1;
PyErr_Clear();
Py_XDECREF(rv);
Py_XDECREF(fs);
return err;
}
#endif /* !__LP64__ */
@ -160,30 +160,30 @@ PyMac_GetFullPathname(FSSpec *fss, char *path, int len)
int
PyMac_GetOSType(PyObject *v, OSType *pr)
{
uint32_t tmp;
if (!PyString_Check(v) || PyString_Size(v) != 4) {
PyErr_SetString(PyExc_TypeError,
"OSType arg must be string of 4 chars");
return 0;
}
memcpy((char *)&tmp, PyString_AsString(v), 4);
*pr = (OSType)ntohl(tmp);
return 1;
uint32_t tmp;
if (!PyString_Check(v) || PyString_Size(v) != 4) {
PyErr_SetString(PyExc_TypeError,
"OSType arg must be string of 4 chars");
return 0;
}
memcpy((char *)&tmp, PyString_AsString(v), 4);
*pr = (OSType)ntohl(tmp);
return 1;
}
/* Convert an OSType value to a 4-char string object */
PyObject *
PyMac_BuildOSType(OSType t)
{
uint32_t tmp = htonl((uint32_t)t);
return PyString_FromStringAndSize((char *)&tmp, 4);
uint32_t tmp = htonl((uint32_t)t);
return PyString_FromStringAndSize((char *)&tmp, 4);
}
/* Convert an NumVersion value to a 4-element tuple */
PyObject *
PyMac_BuildNumVersion(NumVersion t)
{
return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
return Py_BuildValue("(hhhh)", t.majorRev, t.minorAndBugRev, t.stage, t.nonRelRev);
}
@ -191,36 +191,36 @@ PyMac_BuildNumVersion(NumVersion t)
int
PyMac_GetStr255(PyObject *v, Str255 pbuf)
{
int len;
if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
PyErr_SetString(PyExc_TypeError,
"Str255 arg must be string of at most 255 chars");
return 0;
}
pbuf[0] = len;
memcpy((char *)(pbuf+1), PyString_AsString(v), len);
return 1;
int len;
if (!PyString_Check(v) || (len = PyString_Size(v)) > 255) {
PyErr_SetString(PyExc_TypeError,
"Str255 arg must be string of at most 255 chars");
return 0;
}
pbuf[0] = len;
memcpy((char *)(pbuf+1), PyString_AsString(v), len);
return 1;
}
/* Convert a Str255 to a Python string object */
PyObject *
PyMac_BuildStr255(Str255 s)
{
if ( s == NULL ) {
PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
return NULL;
}
return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
if ( s == NULL ) {
PyErr_SetString(PyExc_SystemError, "Str255 pointer is NULL");
return NULL;
}
return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
}
PyObject *
PyMac_BuildOptStr255(Str255 s)
{
if ( s == NULL ) {
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
if ( s == NULL ) {
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromStringAndSize((char *)&s[1], (int)s[0]);
}
@ -232,14 +232,14 @@ PyMac_BuildOptStr255(Str255 s)
int
PyMac_GetRect(PyObject *v, Rect *r)
{
return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
return PyArg_Parse(v, "(hhhh)", &r->left, &r->top, &r->right, &r->bottom);
}
/* Convert a Rect to a Python object */
PyObject *
PyMac_BuildRect(Rect *r)
{
return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
return Py_BuildValue("(hhhh)", r->left, r->top, r->right, r->bottom);
}
@ -250,14 +250,14 @@ PyMac_BuildRect(Rect *r)
int
PyMac_GetPoint(PyObject *v, Point *p)
{
return PyArg_Parse(v, "(hh)", &p->h, &p->v);
return PyArg_Parse(v, "(hh)", &p->h, &p->v);
}
/* Convert a Point to a Python object */
PyObject *
PyMac_BuildPoint(Point p)
{
return Py_BuildValue("(hh)", p.h, p.v);
return Py_BuildValue("(hh)", p.h, p.v);
}
@ -266,73 +266,73 @@ PyMac_BuildPoint(Point p)
int
PyMac_GetEventRecord(PyObject *v, EventRecord *e)
{
return PyArg_Parse(v, "(Hkk(hh)H)",
&e->what,
&e->message,
&e->when,
&e->where.h,
&e->where.v,
&e->modifiers);
return PyArg_Parse(v, "(Hkk(hh)H)",
&e->what,
&e->message,
&e->when,
&e->where.h,
&e->where.v,
&e->modifiers);
}
/* Convert a Rect to an EventRecord object */
PyObject *
PyMac_BuildEventRecord(EventRecord *e)
{
return Py_BuildValue("(hll(hh)h)",
e->what,
e->message,
e->when,
e->where.h,
e->where.v,
e->modifiers);
return Py_BuildValue("(hll(hh)h)",
e->what,
e->message,
e->when,
e->where.h,
e->where.v,
e->modifiers);
}
/* Convert Python object to Fixed */
int
PyMac_GetFixed(PyObject *v, Fixed *f)
{
double d;
if( !PyArg_Parse(v, "d", &d))
return 0;
*f = (Fixed)(d * 0x10000);
return 1;
double d;
if( !PyArg_Parse(v, "d", &d))
return 0;
*f = (Fixed)(d * 0x10000);
return 1;
}
/* Convert a Fixed to a Python object */
PyObject *
PyMac_BuildFixed(Fixed f)
{
double d;
d = f;
d = d / 0x10000;
return Py_BuildValue("d", d);
double d;
d = f;
d = d / 0x10000;
return Py_BuildValue("d", d);
}
/* Convert wide to/from Python int or (hi, lo) tuple. XXXX Should use Python longs */
int
PyMac_Getwide(PyObject *v, wide *rv)
{
if (PyInt_Check(v)) {
rv->hi = 0;
rv->lo = PyInt_AsLong(v);
if( rv->lo & 0x80000000 )
rv->hi = -1;
return 1;
}
return PyArg_Parse(v, "(kk)", &rv->hi, &rv->lo);
if (PyInt_Check(v)) {
rv->hi = 0;
rv->lo = PyInt_AsLong(v);
if( rv->lo & 0x80000000 )
rv->hi = -1;
return 1;
}
return PyArg_Parse(v, "(kk)", &rv->hi, &rv->lo);
}
PyObject *
PyMac_Buildwide(wide *w)
{
if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
(w->hi == -1 && (w->lo & 0x80000000) ) )
return PyInt_FromLong(w->lo);
return Py_BuildValue("(ll)", w->hi, w->lo);
if ( (w->hi == 0 && (w->lo & 0x80000000) == 0) ||
(w->hi == -1 && (w->lo & 0x80000000) ) )
return PyInt_FromLong(w->lo);
return Py_BuildValue("(ll)", w->hi, w->lo);
}
#ifdef USE_TOOLBOX_OBJECT_GLUE
@ -358,8 +358,8 @@ PyObject *routinename(object cobj) { \
if (!PyMacGluePtr_##routinename) { \
if (!PyImport_ImportModule(module)) return NULL; \
if (!PyMacGluePtr_##routinename) { \
PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
return NULL; \
PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
return NULL; \
} \
} \
return (*PyMacGluePtr_##routinename)(cobj); \
@ -372,8 +372,8 @@ int routinename(PyObject *pyobj, object *cobj) { \
if (!PyMacGluePtr_##routinename) { \
if (!PyImport_ImportModule(module)) return 0; \
if (!PyMacGluePtr_##routinename) { \
PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
return 0; \
PyErr_SetString(PyExc_ImportError, "Module did not provide routine: " module ": " #routinename); \
return 0; \
} \
} \
return (*PyMacGluePtr_##routinename)(pyobj, cobj); \

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -20,20 +20,20 @@
Return value (rv):
When 0 <= rv < size, the output conversion was unexceptional, and
rv characters were written to str (excluding a trailing \0 byte at
str[rv]).
When 0 <= rv < size, the output conversion was unexceptional, and
rv characters were written to str (excluding a trailing \0 byte at
str[rv]).
When rv >= size, output conversion was truncated, and a buffer of
size rv+1 would have been needed to avoid truncation. str[size-1]
is \0 in this case.
When rv >= size, output conversion was truncated, and a buffer of
size rv+1 would have been needed to avoid truncation. str[size-1]
is \0 in this case.
When rv < 0, "something bad happened". str[size-1] is \0 in this
case too, but the rest of str is unreliable. It could be that
an error in format codes was detected by libc, or on platforms
with a non-C99 vsnprintf simply that the buffer wasn't big enough
to avoid truncation, or on platforms without any vsnprintf that
PyMem_Malloc couldn't obtain space for a temp buffer.
When rv < 0, "something bad happened". str[size-1] is \0 in this
case too, but the rest of str is unreliable. It could be that
an error in format codes was detected by libc, or on platforms
with a non-C99 vsnprintf simply that the buffer wasn't big enough
to avoid truncation, or on platforms without any vsnprintf that
PyMem_Malloc couldn't obtain space for a temp buffer.
CAUTION: Unlike C99, str != NULL and size > 0 are required.
*/
@ -41,65 +41,65 @@
int
PyOS_snprintf(char *str, size_t size, const char *format, ...)
{
int rc;
va_list va;
int rc;
va_list va;
va_start(va, format);
rc = PyOS_vsnprintf(str, size, format, va);
va_end(va);
return rc;
va_start(va, format);
rc = PyOS_vsnprintf(str, size, format, va);
va_end(va);
return rc;
}
int
PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
{
int len; /* # bytes written, excluding \0 */
int len; /* # bytes written, excluding \0 */
#ifdef HAVE_SNPRINTF
#define _PyOS_vsnprintf_EXTRA_SPACE 1
#else
#define _PyOS_vsnprintf_EXTRA_SPACE 512
char *buffer;
char *buffer;
#endif
assert(str != NULL);
assert(size > 0);
assert(format != NULL);
/* We take a size_t as input but return an int. Sanity check
* our input so that it won't cause an overflow in the
* vsnprintf return value or the buffer malloc size. */
if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
len = -666;
goto Done;
}
assert(str != NULL);
assert(size > 0);
assert(format != NULL);
/* We take a size_t as input but return an int. Sanity check
* our input so that it won't cause an overflow in the
* vsnprintf return value or the buffer malloc size. */
if (size > INT_MAX - _PyOS_vsnprintf_EXTRA_SPACE) {
len = -666;
goto Done;
}
#ifdef HAVE_SNPRINTF
len = vsnprintf(str, size, format, va);
len = vsnprintf(str, size, format, va);
#else
/* Emulate it. */
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
if (buffer == NULL) {
len = -666;
goto Done;
}
/* Emulate it. */
buffer = PyMem_MALLOC(size + _PyOS_vsnprintf_EXTRA_SPACE);
if (buffer == NULL) {
len = -666;
goto Done;
}
len = vsprintf(buffer, format, va);
if (len < 0)
/* ignore the error */;
len = vsprintf(buffer, format, va);
if (len < 0)
/* ignore the error */;
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE)
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf");
else {
const size_t to_copy = (size_t)len < size ?
(size_t)len : size - 1;
assert(to_copy < size);
memcpy(str, buffer, to_copy);
str[to_copy] = '\0';
}
PyMem_FREE(buffer);
else {
const size_t to_copy = (size_t)len < size ?
(size_t)len : size - 1;
assert(to_copy < size);
memcpy(str, buffer, to_copy);
str[to_copy] = '\0';
}
PyMem_FREE(buffer);
#endif
Done:
if (size > 0)
str[size-1] = '\0';
return len;
if (size > 0)
str[size-1] = '\0';
return len;
#undef _PyOS_vsnprintf_EXTRA_SPACE
}

View file

@ -18,43 +18,43 @@
* i * base doesn't overflow unsigned long.
*/
static unsigned long smallmax[] = {
0, /* bases 0 and 1 are invalid */
0,
ULONG_MAX / 2,
ULONG_MAX / 3,
ULONG_MAX / 4,
ULONG_MAX / 5,
ULONG_MAX / 6,
ULONG_MAX / 7,
ULONG_MAX / 8,
ULONG_MAX / 9,
ULONG_MAX / 10,
ULONG_MAX / 11,
ULONG_MAX / 12,
ULONG_MAX / 13,
ULONG_MAX / 14,
ULONG_MAX / 15,
ULONG_MAX / 16,
ULONG_MAX / 17,
ULONG_MAX / 18,
ULONG_MAX / 19,
ULONG_MAX / 20,
ULONG_MAX / 21,
ULONG_MAX / 22,
ULONG_MAX / 23,
ULONG_MAX / 24,
ULONG_MAX / 25,
ULONG_MAX / 26,
ULONG_MAX / 27,
ULONG_MAX / 28,
ULONG_MAX / 29,
ULONG_MAX / 30,
ULONG_MAX / 31,
ULONG_MAX / 32,
ULONG_MAX / 33,
ULONG_MAX / 34,
ULONG_MAX / 35,
ULONG_MAX / 36,
0, /* bases 0 and 1 are invalid */
0,
ULONG_MAX / 2,
ULONG_MAX / 3,
ULONG_MAX / 4,
ULONG_MAX / 5,
ULONG_MAX / 6,
ULONG_MAX / 7,
ULONG_MAX / 8,
ULONG_MAX / 9,
ULONG_MAX / 10,
ULONG_MAX / 11,
ULONG_MAX / 12,
ULONG_MAX / 13,
ULONG_MAX / 14,
ULONG_MAX / 15,
ULONG_MAX / 16,
ULONG_MAX / 17,
ULONG_MAX / 18,
ULONG_MAX / 19,
ULONG_MAX / 20,
ULONG_MAX / 21,
ULONG_MAX / 22,
ULONG_MAX / 23,
ULONG_MAX / 24,
ULONG_MAX / 25,
ULONG_MAX / 26,
ULONG_MAX / 27,
ULONG_MAX / 28,
ULONG_MAX / 29,
ULONG_MAX / 30,
ULONG_MAX / 31,
ULONG_MAX / 32,
ULONG_MAX / 33,
ULONG_MAX / 34,
ULONG_MAX / 35,
ULONG_MAX / 36,
};
/* maximum digits that can't ever overflow for bases 2 through 36,
@ -63,223 +63,223 @@ static unsigned long smallmax[] = {
*/
#if SIZEOF_LONG == 4
static int digitlimit[] = {
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
0, 0, 32, 20, 16, 13, 12, 11, 10, 10, /* 0 - 9 */
9, 9, 8, 8, 8, 8, 8, 7, 7, 7, /* 10 - 19 */
7, 7, 7, 7, 6, 6, 6, 6, 6, 6, /* 20 - 29 */
6, 6, 6, 6, 6, 6, 6}; /* 30 - 36 */
#elif SIZEOF_LONG == 8
/* [int(math.floor(math.log(2**64, i))) for i in range(2, 37)] */
static int digitlimit[] = {
0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
0, 0, 64, 40, 32, 27, 24, 22, 21, 20, /* 0 - 9 */
19, 18, 17, 17, 16, 16, 16, 15, 15, 15, /* 10 - 19 */
14, 14, 14, 14, 13, 13, 13, 13, 13, 13, /* 20 - 29 */
13, 12, 12, 12, 12, 12, 12}; /* 30 - 36 */
#else
#error "Need table for SIZEOF_LONG"
#endif
/*
** strtoul
** This is a general purpose routine for converting
** an ascii string to an integer in an arbitrary base.
** Leading white space is ignored. If 'base' is zero
** it looks for a leading 0, 0b, 0B, 0o, 0O, 0x or 0X
** to tell which base. If these are absent it defaults
** to 10. Base must be 0 or between 2 and 36 (inclusive).
** If 'ptr' is non-NULL it will contain a pointer to
** the end of the scan.
** Errors due to bad pointers will probably result in
** exceptions - we don't check for them.
** strtoul
** This is a general purpose routine for converting
** an ascii string to an integer in an arbitrary base.
** Leading white space is ignored. If 'base' is zero
** it looks for a leading 0, 0b, 0B, 0o, 0O, 0x or 0X
** to tell which base. If these are absent it defaults
** to 10. Base must be 0 or between 2 and 36 (inclusive).
** If 'ptr' is non-NULL it will contain a pointer to
** the end of the scan.
** Errors due to bad pointers will probably result in
** exceptions - we don't check for them.
*/
unsigned long
PyOS_strtoul(register char *str, char **ptr, int base)
{
register unsigned long result = 0; /* return value of the function */
register int c; /* current input character */
register int ovlimit; /* required digits to overflow */
register unsigned long result = 0; /* return value of the function */
register int c; /* current input character */
register int ovlimit; /* required digits to overflow */
/* skip leading white space */
while (*str && isspace(Py_CHARMASK(*str)))
++str;
/* skip leading white space */
while (*str && isspace(Py_CHARMASK(*str)))
++str;
/* check for leading 0 or 0x for auto-base or base 16 */
switch (base) {
case 0: /* look for leading 0, 0b, 0o or 0x */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 16;
} else if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 8;
} else if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 2;
} else {
base = 8;
}
}
else
base = 10;
break;
/* check for leading 0 or 0x for auto-base or base 16 */
switch (base) {
case 0: /* look for leading 0, 0b, 0o or 0x */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 16;
} else if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 8;
} else if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = str;
return 0;
}
++str;
base = 2;
} else {
base = 8;
}
}
else
base = 10;
break;
case 2: /* skip leading 0b or 0B */
if (*str == '0') {
++str;
if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
case 2: /* skip leading 0b or 0B */
if (*str == '0') {
++str;
if (*str == 'b' || *str == 'B') {
/* there must be at least one digit after 0b */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 2) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
case 8: /* skip leading 0o or 0O */
if (*str == '0') {
++str;
if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
case 8: /* skip leading 0o or 0O */
if (*str == '0') {
++str;
if (*str == 'o' || *str == 'O') {
/* there must be at least one digit after 0o */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 8) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
case 16: /* skip leading 0x or 0X */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
}
case 16: /* skip leading 0x or 0X */
if (*str == '0') {
++str;
if (*str == 'x' || *str == 'X') {
/* there must be at least one digit after 0x */
if (_PyLong_DigitValue[Py_CHARMASK(str[1])] >= 16) {
if (ptr)
*ptr = str;
return 0;
}
++str;
}
}
break;
}
/* catch silly bases */
if (base < 2 || base > 36) {
if (ptr)
*ptr = str;
return 0;
}
/* catch silly bases */
if (base < 2 || base > 36) {
if (ptr)
*ptr = str;
return 0;
}
/* skip leading zeroes */
while (*str == '0')
++str;
/* skip leading zeroes */
while (*str == '0')
++str;
/* base is guaranteed to be in [2, 36] at this point */
ovlimit = digitlimit[base];
/* base is guaranteed to be in [2, 36] at this point */
ovlimit = digitlimit[base];
/* do the conversion until non-digit character encountered */
while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
if (ovlimit > 0) /* no overflow check required */
result = result * base + c;
else { /* requires overflow check */
register unsigned long temp_result;
/* do the conversion until non-digit character encountered */
while ((c = _PyLong_DigitValue[Py_CHARMASK(*str)]) < base) {
if (ovlimit > 0) /* no overflow check required */
result = result * base + c;
else { /* requires overflow check */
register unsigned long temp_result;
if (ovlimit < 0) /* guaranteed overflow */
goto overflowed;
if (ovlimit < 0) /* guaranteed overflow */
goto overflowed;
/* there could be an overflow */
/* check overflow just from shifting */
if (result > smallmax[base])
goto overflowed;
/* there could be an overflow */
/* check overflow just from shifting */
if (result > smallmax[base])
goto overflowed;
result *= base;
result *= base;
/* check overflow from the digit's value */
temp_result = result + c;
if (temp_result < result)
goto overflowed;
/* check overflow from the digit's value */
temp_result = result + c;
if (temp_result < result)
goto overflowed;
result = temp_result;
}
result = temp_result;
}
++str;
--ovlimit;
}
++str;
--ovlimit;
}
/* set pointer to point to the last character scanned */
if (ptr)
*ptr = str;
/* set pointer to point to the last character scanned */
if (ptr)
*ptr = str;
return result;
return result;
overflowed:
if (ptr) {
/* spool through remaining digit characters */
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
++str;
*ptr = str;
}
errno = ERANGE;
return (unsigned long)-1;
if (ptr) {
/* spool through remaining digit characters */
while (_PyLong_DigitValue[Py_CHARMASK(*str)] < base)
++str;
*ptr = str;
}
errno = ERANGE;
return (unsigned long)-1;
}
/* Checking for overflow in PyOS_strtol is a PITA; see comments
* about PY_ABS_LONG_MIN in longobject.c.
*/
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
long
PyOS_strtol(char *str, char **ptr, int base)
{
long result;
unsigned long uresult;
char sign;
long result;
unsigned long uresult;
char sign;
while (*str && isspace(Py_CHARMASK(*str)))
str++;
while (*str && isspace(Py_CHARMASK(*str)))
str++;
sign = *str;
if (sign == '+' || sign == '-')
str++;
sign = *str;
if (sign == '+' || sign == '-')
str++;
uresult = PyOS_strtoul(str, ptr, base);
uresult = PyOS_strtoul(str, ptr, base);
if (uresult <= (unsigned long)LONG_MAX) {
result = (long)uresult;
if (sign == '-')
result = -result;
}
else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
result = LONG_MIN;
}
else {
errno = ERANGE;
result = LONG_MAX;
}
return result;
if (uresult <= (unsigned long)LONG_MAX) {
result = (long)uresult;
if (sign == '-')
result = -result;
}
else if (sign == '-' && uresult == PY_ABS_LONG_MIN) {
result = LONG_MIN;
}
else {
errno = ERANGE;
result = LONG_MAX;
}
return result;
}

File diff suppressed because it is too large Load diff

View file

@ -12,32 +12,32 @@
*/
#define DEFAULT_BLOCK_SIZE 8192
#define ALIGNMENT 8
#define ALIGNMENT_MASK (ALIGNMENT - 1)
#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
#define ALIGNMENT 8
#define ALIGNMENT_MASK (ALIGNMENT - 1)
#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
typedef struct _block {
/* Total number of bytes owned by this block available to pass out.
* Read-only after initialization. The first such byte starts at
* ab_mem.
*/
size_t ab_size;
/* Total number of bytes owned by this block available to pass out.
* Read-only after initialization. The first such byte starts at
* ab_mem.
*/
size_t ab_size;
/* Total number of bytes already passed out. The next byte available
* to pass out starts at ab_mem + ab_offset.
*/
size_t ab_offset;
/* Total number of bytes already passed out. The next byte available
* to pass out starts at ab_mem + ab_offset.
*/
size_t ab_offset;
/* An arena maintains a singly-linked, NULL-terminated list of
* all blocks owned by the arena. These are linked via the
* ab_next member.
*/
struct _block *ab_next;
/* An arena maintains a singly-linked, NULL-terminated list of
* all blocks owned by the arena. These are linked via the
* ab_next member.
*/
struct _block *ab_next;
/* Pointer to the first allocatable byte owned by this block. Read-
* only after initialization.
*/
void *ab_mem;
/* Pointer to the first allocatable byte owned by this block. Read-
* only after initialization.
*/
void *ab_mem;
} block;
/* The arena manages two kinds of memory, blocks of raw memory
@ -46,175 +46,175 @@ typedef struct _block {
*/
struct _arena {
/* Pointer to the first block allocated for the arena, never NULL.
It is used only to find the first block when the arena is
being freed.
*/
block *a_head;
/* Pointer to the first block allocated for the arena, never NULL.
It is used only to find the first block when the arena is
being freed.
*/
block *a_head;
/* Pointer to the block currently used for allocation. It's
ab_next field should be NULL. If it is not-null after a
call to block_alloc(), it means a new block has been allocated
and a_cur should be reset to point it.
*/
block *a_cur;
/* Pointer to the block currently used for allocation. It's
ab_next field should be NULL. If it is not-null after a
call to block_alloc(), it means a new block has been allocated
and a_cur should be reset to point it.
*/
block *a_cur;
/* A Python list object containing references to all the PyObject
pointers associated with this area. They will be DECREFed
when the arena is freed.
*/
PyObject *a_objects;
/* A Python list object containing references to all the PyObject
pointers associated with this area. They will be DECREFed
when the arena is freed.
*/
PyObject *a_objects;
#if defined(Py_DEBUG)
/* Debug output */
size_t total_allocs;
size_t total_size;
size_t total_blocks;
size_t total_block_size;
size_t total_big_blocks;
/* Debug output */
size_t total_allocs;
size_t total_size;
size_t total_blocks;
size_t total_block_size;
size_t total_big_blocks;
#endif
};
static block *
block_new(size_t size)
{
/* Allocate header and block as one unit.
ab_mem points just past header. */
block *b = (block *)malloc(sizeof(block) + size);
if (!b)
return NULL;
b->ab_size = size;
b->ab_mem = (void *)(b + 1);
b->ab_next = NULL;
b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) -
(Py_uintptr_t)(b->ab_mem);
return b;
/* Allocate header and block as one unit.
ab_mem points just past header. */
block *b = (block *)malloc(sizeof(block) + size);
if (!b)
return NULL;
b->ab_size = size;
b->ab_mem = (void *)(b + 1);
b->ab_next = NULL;
b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) -
(Py_uintptr_t)(b->ab_mem);
return b;
}
static void
block_free(block *b) {
while (b) {
block *next = b->ab_next;
free(b);
b = next;
}
while (b) {
block *next = b->ab_next;
free(b);
b = next;
}
}
static void *
block_alloc(block *b, size_t size)
{
void *p;
assert(b);
size = ROUNDUP(size);
if (b->ab_offset + size > b->ab_size) {
/* If we need to allocate more memory than will fit in
the default block, allocate a one-off block that is
exactly the right size. */
/* TODO(jhylton): Think about space waste at end of block */
block *newbl = block_new(
size < DEFAULT_BLOCK_SIZE ?
DEFAULT_BLOCK_SIZE : size);
if (!newbl)
return NULL;
assert(!b->ab_next);
b->ab_next = newbl;
b = newbl;
}
void *p;
assert(b);
size = ROUNDUP(size);
if (b->ab_offset + size > b->ab_size) {
/* If we need to allocate more memory than will fit in
the default block, allocate a one-off block that is
exactly the right size. */
/* TODO(jhylton): Think about space waste at end of block */
block *newbl = block_new(
size < DEFAULT_BLOCK_SIZE ?
DEFAULT_BLOCK_SIZE : size);
if (!newbl)
return NULL;
assert(!b->ab_next);
b->ab_next = newbl;
b = newbl;
}
assert(b->ab_offset + size <= b->ab_size);
p = (void *)(((char *)b->ab_mem) + b->ab_offset);
b->ab_offset += size;
return p;
assert(b->ab_offset + size <= b->ab_size);
p = (void *)(((char *)b->ab_mem) + b->ab_offset);
b->ab_offset += size;
return p;
}
PyArena *
PyArena_New()
{
PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
if (!arena)
return (PyArena*)PyErr_NoMemory();
PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
if (!arena)
return (PyArena*)PyErr_NoMemory();
arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
arena->a_cur = arena->a_head;
if (!arena->a_head) {
free((void *)arena);
return (PyArena*)PyErr_NoMemory();
}
arena->a_objects = PyList_New(0);
if (!arena->a_objects) {
block_free(arena->a_head);
free((void *)arena);
return (PyArena*)PyErr_NoMemory();
}
arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
arena->a_cur = arena->a_head;
if (!arena->a_head) {
free((void *)arena);
return (PyArena*)PyErr_NoMemory();
}
arena->a_objects = PyList_New(0);
if (!arena->a_objects) {
block_free(arena->a_head);
free((void *)arena);
return (PyArena*)PyErr_NoMemory();
}
#if defined(Py_DEBUG)
arena->total_allocs = 0;
arena->total_size = 0;
arena->total_blocks = 1;
arena->total_block_size = DEFAULT_BLOCK_SIZE;
arena->total_big_blocks = 0;
arena->total_allocs = 0;
arena->total_size = 0;
arena->total_blocks = 1;
arena->total_block_size = DEFAULT_BLOCK_SIZE;
arena->total_big_blocks = 0;
#endif
return arena;
return arena;
}
void
PyArena_Free(PyArena *arena)
{
int r;
assert(arena);
int r;
assert(arena);
#if defined(Py_DEBUG)
/*
fprintf(stderr,
"alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
arena->total_allocs, arena->total_size, arena->total_blocks,
arena->total_block_size, arena->total_big_blocks,
PyList_Size(arena->a_objects));
*/
/*
fprintf(stderr,
"alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
arena->total_allocs, arena->total_size, arena->total_blocks,
arena->total_block_size, arena->total_big_blocks,
PyList_Size(arena->a_objects));
*/
#endif
block_free(arena->a_head);
/* This property normally holds, except when the code being compiled
is sys.getobjects(0), in which case there will be two references.
assert(arena->a_objects->ob_refcnt == 1);
*/
block_free(arena->a_head);
/* This property normally holds, except when the code being compiled
is sys.getobjects(0), in which case there will be two references.
assert(arena->a_objects->ob_refcnt == 1);
*/
/* Clear all the elements from the list. This is necessary
to guarantee that they will be DECREFed. */
r = PyList_SetSlice(arena->a_objects,
0, PyList_GET_SIZE(arena->a_objects), NULL);
assert(r == 0);
assert(PyList_GET_SIZE(arena->a_objects) == 0);
Py_DECREF(arena->a_objects);
free(arena);
/* Clear all the elements from the list. This is necessary
to guarantee that they will be DECREFed. */
r = PyList_SetSlice(arena->a_objects,
0, PyList_GET_SIZE(arena->a_objects), NULL);
assert(r == 0);
assert(PyList_GET_SIZE(arena->a_objects) == 0);
Py_DECREF(arena->a_objects);
free(arena);
}
void *
PyArena_Malloc(PyArena *arena, size_t size)
{
void *p = block_alloc(arena->a_cur, size);
if (!p)
return PyErr_NoMemory();
void *p = block_alloc(arena->a_cur, size);
if (!p)
return PyErr_NoMemory();
#if defined(Py_DEBUG)
arena->total_allocs++;
arena->total_size += size;
arena->total_allocs++;
arena->total_size += size;
#endif
/* Reset cur if we allocated a new block. */
if (arena->a_cur->ab_next) {
arena->a_cur = arena->a_cur->ab_next;
/* Reset cur if we allocated a new block. */
if (arena->a_cur->ab_next) {
arena->a_cur = arena->a_cur->ab_next;
#if defined(Py_DEBUG)
arena->total_blocks++;
arena->total_block_size += arena->a_cur->ab_size;
if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
++arena->total_big_blocks;
arena->total_blocks++;
arena->total_block_size += arena->a_cur->ab_size;
if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
++arena->total_big_blocks;
#endif
}
return p;
}
return p;
}
int
PyArena_AddPyObject(PyArena *arena, PyObject *obj)
{
int r = PyList_Append(arena->a_objects, obj);
if (r >= 0) {
Py_DECREF(obj);
}
return r;
int r = PyList_Append(arena->a_objects, obj);
if (r >= 0) {
Py_DECREF(obj);
}
return r;
}

View file

@ -7,30 +7,30 @@
thus rounding from extended precision to double precision. */
double _Py_force_double(double x)
{
volatile double y;
y = x;
return y;
volatile double y;
y = x;
return y;
}
#endif
#ifndef HAVE_HYPOT
double hypot(double x, double y)
{
double yx;
double yx;
x = fabs(x);
y = fabs(y);
if (x < y) {
double temp = x;
x = y;
y = temp;
}
if (x == 0.)
return 0.;
else {
yx = y/x;
return x*sqrt(1.+yx*yx);
}
x = fabs(x);
y = fabs(y);
if (x < y) {
double temp = x;
x = y;
y = temp;
}
if (x == 0.)
return 0.;
else {
yx = y/x;
return x*sqrt(1.+yx*yx);
}
}
#endif /* HAVE_HYPOT */
@ -38,12 +38,12 @@ double hypot(double x, double y)
double
copysign(double x, double y)
{
/* use atan2 to distinguish -0. from 0. */
if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) {
return fabs(x);
} else {
return -fabs(x);
}
/* use atan2 to distinguish -0. from 0. */
if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) {
return fabs(x);
} else {
return -fabs(x);
}
}
#endif /* HAVE_COPYSIGN */
@ -53,41 +53,41 @@ copysign(double x, double y)
double
log1p(double x)
{
/* For x small, we use the following approach. Let y be the nearest
float to 1+x, then
/* For x small, we use the following approach. Let y be the nearest
float to 1+x, then
1+x = y * (1 - (y-1-x)/y)
1+x = y * (1 - (y-1-x)/y)
so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny,
the second term is well approximated by (y-1-x)/y. If abs(x) >=
DBL_EPSILON/2 or the rounding-mode is some form of round-to-nearest
then y-1-x will be exactly representable, and is computed exactly
by (y-1)-x.
so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny,
the second term is well approximated by (y-1-x)/y. If abs(x) >=
DBL_EPSILON/2 or the rounding-mode is some form of round-to-nearest
then y-1-x will be exactly representable, and is computed exactly
by (y-1)-x.
If abs(x) < DBL_EPSILON/2 and the rounding mode is not known to be
round-to-nearest then this method is slightly dangerous: 1+x could
be rounded up to 1+DBL_EPSILON instead of down to 1, and in that
case y-1-x will not be exactly representable any more and the
result can be off by many ulps. But this is easily fixed: for a
floating-point number |x| < DBL_EPSILON/2., the closest
floating-point number to log(1+x) is exactly x.
*/
If abs(x) < DBL_EPSILON/2 and the rounding mode is not known to be
round-to-nearest then this method is slightly dangerous: 1+x could
be rounded up to 1+DBL_EPSILON instead of down to 1, and in that
case y-1-x will not be exactly representable any more and the
result can be off by many ulps. But this is easily fixed: for a
floating-point number |x| < DBL_EPSILON/2., the closest
floating-point number to log(1+x) is exactly x.
*/
double y;
if (fabs(x) < DBL_EPSILON/2.) {
return x;
} else if (-0.5 <= x && x <= 1.) {
/* WARNING: it's possible than an overeager compiler
will incorrectly optimize the following two lines
to the equivalent of "return log(1.+x)". If this
happens, then results from log1p will be inaccurate
for small x. */
y = 1.+x;
return log(y)-((y-1.)-x)/y;
} else {
/* NaNs and infinities should end up here */
return log(1.+x);
}
double y;
if (fabs(x) < DBL_EPSILON/2.) {
return x;
} else if (-0.5 <= x && x <= 1.) {
/* WARNING: it's possible than an overeager compiler
will incorrectly optimize the following two lines
to the equivalent of "return log(1.+x)". If this
happens, then results from log1p will be inaccurate
for small x. */
y = 1.+x;
return log(y)-((y-1.)-x)/y;
} else {
/* NaNs and infinities should end up here */
return log(1.+x);
}
}
#endif /* HAVE_LOG1P */
@ -97,7 +97,7 @@ log1p(double x)
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
@ -109,51 +109,51 @@ static const double zero = 0.0;
/* asinh(x)
* Method :
* Based on
* asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
* we have
* asinh(x) := x if 1+x*x=1,
* := sign(x)*(log(x)+ln2)) for large |x|, else
* := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
* := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
* Based on
* asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
* we have
* asinh(x) := x if 1+x*x=1,
* := sign(x)*(log(x)+ln2)) for large |x|, else
* := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
* := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
*/
#ifndef HAVE_ASINH
double
asinh(double x)
{
double w;
double absx = fabs(x);
{
double w;
double absx = fabs(x);
if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
return x+x;
}
if (absx < two_pow_m28) { /* |x| < 2**-28 */
return x; /* return x inexact except 0 */
}
if (absx > two_pow_p28) { /* |x| > 2**28 */
w = log(absx)+ln2;
}
else if (absx > 2.0) { /* 2 < |x| < 2**28 */
w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
}
else { /* 2**-28 <= |x| < 2= */
double t = x*x;
w = log1p(absx + t / (1.0 + sqrt(1.0 + t)));
}
return copysign(w, x);
if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
return x+x;
}
if (absx < two_pow_m28) { /* |x| < 2**-28 */
return x; /* return x inexact except 0 */
}
if (absx > two_pow_p28) { /* |x| > 2**28 */
w = log(absx)+ln2;
}
else if (absx > 2.0) { /* 2 < |x| < 2**28 */
w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
}
else { /* 2**-28 <= |x| < 2= */
double t = x*x;
w = log1p(absx + t / (1.0 + sqrt(1.0 + t)));
}
return copysign(w, x);
}
#endif /* HAVE_ASINH */
/* acosh(x)
* Method :
* Based on
* acosh(x) = log [ x + sqrt(x*x-1) ]
* acosh(x) = log [ x + sqrt(x*x-1) ]
* we have
* acosh(x) := log(x)+ln2, if x is large; else
* acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
* acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
* acosh(x) := log(x)+ln2, if x is large; else
* acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
* acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
*
* Special cases:
* acosh(x) is NaN with signal if x<1.
@ -164,35 +164,35 @@ asinh(double x)
double
acosh(double x)
{
if (Py_IS_NAN(x)) {
return x+x;
}
if (x < 1.) { /* x < 1; return a signaling NaN */
errno = EDOM;
if (Py_IS_NAN(x)) {
return x+x;
}
if (x < 1.) { /* x < 1; return a signaling NaN */
errno = EDOM;
#ifdef Py_NAN
return Py_NAN;
return Py_NAN;
#else
return (x-x)/(x-x);
return (x-x)/(x-x);
#endif
}
else if (x >= two_pow_p28) { /* x > 2**28 */
if (Py_IS_INFINITY(x)) {
return x+x;
} else {
return log(x)+ln2; /* acosh(huge)=log(2x) */
}
}
else if (x == 1.) {
return 0.0; /* acosh(1) = 0 */
}
else if (x > 2.) { /* 2 < x < 2**28 */
double t = x*x;
return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
}
else { /* 1 < x <= 2 */
double t = x - 1.0;
return log1p(t + sqrt(2.0*t + t*t));
}
}
else if (x >= two_pow_p28) { /* x > 2**28 */
if (Py_IS_INFINITY(x)) {
return x+x;
} else {
return log(x)+ln2; /* acosh(huge)=log(2x) */
}
}
else if (x == 1.) {
return 0.0; /* acosh(1) = 0 */
}
else if (x > 2.) { /* 2 < x < 2**28 */
double t = x*x;
return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
}
else { /* 1 < x <= 2 */
double t = x - 1.0;
return log1p(t + sqrt(2.0*t + t*t));
}
}
#endif /* HAVE_ACOSH */
@ -200,9 +200,9 @@ acosh(double x)
* Method :
* 1.Reduced x to positive by atanh(-x) = -atanh(x)
* 2.For x>=0.5
* 1 2x x
* 1 2x x
* atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
* 2 1 - x 1 - x
* 2 1 - x 1 - x
*
* For x<0.5
* atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
@ -217,31 +217,31 @@ acosh(double x)
double
atanh(double x)
{
double absx;
double t;
double absx;
double t;
if (Py_IS_NAN(x)) {
return x+x;
}
absx = fabs(x);
if (absx >= 1.) { /* |x| >= 1 */
errno = EDOM;
if (Py_IS_NAN(x)) {
return x+x;
}
absx = fabs(x);
if (absx >= 1.) { /* |x| >= 1 */
errno = EDOM;
#ifdef Py_NAN
return Py_NAN;
return Py_NAN;
#else
return x/zero;
return x/zero;
#endif
}
if (absx < two_pow_m28) { /* |x| < 2**-28 */
return x;
}
if (absx < 0.5) { /* |x| < 0.5 */
t = absx+absx;
t = 0.5 * log1p(t + t*absx / (1.0 - absx));
}
else { /* 0.5 <= |x| <= 1.0 */
t = 0.5 * log1p((absx + absx) / (1.0 - absx));
}
return copysign(t, x);
}
if (absx < two_pow_m28) { /* |x| < 2**-28 */
return x;
}
if (absx < 0.5) { /* |x| < 0.5 */
t = absx+absx;
t = 0.5 * log1p(t + t*absx / (1.0 - absx));
}
else { /* 0.5 <= |x| <= 1.0 */
t = 0.5 * log1p((absx + absx) / (1.0 - absx));
}
return copysign(t, x);
}
#endif /* HAVE_ATANH */

View file

@ -58,92 +58,92 @@ static void _PyGILState_NoteThreadState(PyThreadState* tstate);
PyInterpreterState *
PyInterpreterState_New(void)
{
PyInterpreterState *interp = (PyInterpreterState *)
malloc(sizeof(PyInterpreterState));
PyInterpreterState *interp = (PyInterpreterState *)
malloc(sizeof(PyInterpreterState));
if (interp != NULL) {
HEAD_INIT();
if (interp != NULL) {
HEAD_INIT();
#ifdef WITH_THREAD
if (head_mutex == NULL)
Py_FatalError("Can't initialize threads for interpreter");
if (head_mutex == NULL)
Py_FatalError("Can't initialize threads for interpreter");
#endif
interp->modules = NULL;
interp->modules_reloading = NULL;
interp->sysdict = NULL;
interp->builtins = NULL;
interp->tstate_head = NULL;
interp->codec_search_path = NULL;
interp->codec_search_cache = NULL;
interp->codec_error_registry = NULL;
interp->modules = NULL;
interp->modules_reloading = NULL;
interp->sysdict = NULL;
interp->builtins = NULL;
interp->tstate_head = NULL;
interp->codec_search_path = NULL;
interp->codec_search_cache = NULL;
interp->codec_error_registry = NULL;
#ifdef HAVE_DLOPEN
#ifdef RTLD_NOW
interp->dlopenflags = RTLD_NOW;
interp->dlopenflags = RTLD_NOW;
#else
interp->dlopenflags = RTLD_LAZY;
interp->dlopenflags = RTLD_LAZY;
#endif
#endif
#ifdef WITH_TSC
interp->tscdump = 0;
interp->tscdump = 0;
#endif
HEAD_LOCK();
interp->next = interp_head;
interp_head = interp;
HEAD_UNLOCK();
}
HEAD_LOCK();
interp->next = interp_head;
interp_head = interp;
HEAD_UNLOCK();
}
return interp;
return interp;
}
void
PyInterpreterState_Clear(PyInterpreterState *interp)
{
PyThreadState *p;
HEAD_LOCK();
for (p = interp->tstate_head; p != NULL; p = p->next)
PyThreadState_Clear(p);
HEAD_UNLOCK();
Py_CLEAR(interp->codec_search_path);
Py_CLEAR(interp->codec_search_cache);
Py_CLEAR(interp->codec_error_registry);
Py_CLEAR(interp->modules);
Py_CLEAR(interp->modules_reloading);
Py_CLEAR(interp->sysdict);
Py_CLEAR(interp->builtins);
PyThreadState *p;
HEAD_LOCK();
for (p = interp->tstate_head; p != NULL; p = p->next)
PyThreadState_Clear(p);
HEAD_UNLOCK();
Py_CLEAR(interp->codec_search_path);
Py_CLEAR(interp->codec_search_cache);
Py_CLEAR(interp->codec_error_registry);
Py_CLEAR(interp->modules);
Py_CLEAR(interp->modules_reloading);
Py_CLEAR(interp->sysdict);
Py_CLEAR(interp->builtins);
}
static void
zapthreads(PyInterpreterState *interp)
{
PyThreadState *p;
/* No need to lock the mutex here because this should only happen
when the threads are all really dead (XXX famous last words). */
while ((p = interp->tstate_head) != NULL) {
PyThreadState_Delete(p);
}
PyThreadState *p;
/* No need to lock the mutex here because this should only happen
when the threads are all really dead (XXX famous last words). */
while ((p = interp->tstate_head) != NULL) {
PyThreadState_Delete(p);
}
}
void
PyInterpreterState_Delete(PyInterpreterState *interp)
{
PyInterpreterState **p;
zapthreads(interp);
HEAD_LOCK();
for (p = &interp_head; ; p = &(*p)->next) {
if (*p == NULL)
Py_FatalError(
"PyInterpreterState_Delete: invalid interp");
if (*p == interp)
break;
}
if (interp->tstate_head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining threads");
*p = interp->next;
HEAD_UNLOCK();
free(interp);
PyInterpreterState **p;
zapthreads(interp);
HEAD_LOCK();
for (p = &interp_head; ; p = &(*p)->next) {
if (*p == NULL)
Py_FatalError(
"PyInterpreterState_Delete: invalid interp");
if (*p == interp)
break;
}
if (interp->tstate_head != NULL)
Py_FatalError("PyInterpreterState_Delete: remaining threads");
*p = interp->next;
HEAD_UNLOCK();
free(interp);
}
@ -151,104 +151,104 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
static struct _frame *
threadstate_getframe(PyThreadState *self)
{
return self->frame;
return self->frame;
}
static PyThreadState *
new_threadstate(PyInterpreterState *interp, int init)
{
PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
PyThreadState *tstate = (PyThreadState *)malloc(sizeof(PyThreadState));
if (_PyThreadState_GetFrame == NULL)
_PyThreadState_GetFrame = threadstate_getframe;
if (_PyThreadState_GetFrame == NULL)
_PyThreadState_GetFrame = threadstate_getframe;
if (tstate != NULL) {
tstate->interp = interp;
if (tstate != NULL) {
tstate->interp = interp;
tstate->frame = NULL;
tstate->recursion_depth = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
tstate->tick_counter = 0;
tstate->gilstate_counter = 0;
tstate->async_exc = NULL;
tstate->frame = NULL;
tstate->recursion_depth = 0;
tstate->tracing = 0;
tstate->use_tracing = 0;
tstate->tick_counter = 0;
tstate->gilstate_counter = 0;
tstate->async_exc = NULL;
#ifdef WITH_THREAD
tstate->thread_id = PyThread_get_thread_ident();
tstate->thread_id = PyThread_get_thread_ident();
#else
tstate->thread_id = 0;
tstate->thread_id = 0;
#endif
tstate->dict = NULL;
tstate->dict = NULL;
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
tstate->exc_type = NULL;
tstate->exc_value = NULL;
tstate->exc_traceback = NULL;
tstate->exc_type = NULL;
tstate->exc_value = NULL;
tstate->exc_traceback = NULL;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
tstate->c_profileobj = NULL;
tstate->c_traceobj = NULL;
if (init)
_PyThreadState_Init(tstate);
if (init)
_PyThreadState_Init(tstate);
HEAD_LOCK();
tstate->next = interp->tstate_head;
interp->tstate_head = tstate;
HEAD_UNLOCK();
}
HEAD_LOCK();
tstate->next = interp->tstate_head;
interp->tstate_head = tstate;
HEAD_UNLOCK();
}
return tstate;
return tstate;
}
PyThreadState *
PyThreadState_New(PyInterpreterState *interp)
{
return new_threadstate(interp, 1);
return new_threadstate(interp, 1);
}
PyThreadState *
_PyThreadState_Prealloc(PyInterpreterState *interp)
{
return new_threadstate(interp, 0);
return new_threadstate(interp, 0);
}
void
_PyThreadState_Init(PyThreadState *tstate)
{
#ifdef WITH_THREAD
_PyGILState_NoteThreadState(tstate);
_PyGILState_NoteThreadState(tstate);
#endif
}
void
PyThreadState_Clear(PyThreadState *tstate)
{
if (Py_VerboseFlag && tstate->frame != NULL)
fprintf(stderr,
"PyThreadState_Clear: warning: thread still has a frame\n");
if (Py_VerboseFlag && tstate->frame != NULL)
fprintf(stderr,
"PyThreadState_Clear: warning: thread still has a frame\n");
Py_CLEAR(tstate->frame);
Py_CLEAR(tstate->frame);
Py_CLEAR(tstate->dict);
Py_CLEAR(tstate->async_exc);
Py_CLEAR(tstate->dict);
Py_CLEAR(tstate->async_exc);
Py_CLEAR(tstate->curexc_type);
Py_CLEAR(tstate->curexc_value);
Py_CLEAR(tstate->curexc_traceback);
Py_CLEAR(tstate->curexc_type);
Py_CLEAR(tstate->curexc_value);
Py_CLEAR(tstate->curexc_traceback);
Py_CLEAR(tstate->exc_type);
Py_CLEAR(tstate->exc_value);
Py_CLEAR(tstate->exc_traceback);
Py_CLEAR(tstate->exc_type);
Py_CLEAR(tstate->exc_value);
Py_CLEAR(tstate->exc_traceback);
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
Py_CLEAR(tstate->c_profileobj);
Py_CLEAR(tstate->c_traceobj);
tstate->c_profilefunc = NULL;
tstate->c_tracefunc = NULL;
Py_CLEAR(tstate->c_profileobj);
Py_CLEAR(tstate->c_traceobj);
}
@ -256,50 +256,50 @@ PyThreadState_Clear(PyThreadState *tstate)
static void
tstate_delete_common(PyThreadState *tstate)
{
PyInterpreterState *interp;
PyThreadState **p;
PyThreadState *prev_p = NULL;
if (tstate == NULL)
Py_FatalError("PyThreadState_Delete: NULL tstate");
interp = tstate->interp;
if (interp == NULL)
Py_FatalError("PyThreadState_Delete: NULL interp");
HEAD_LOCK();
for (p = &interp->tstate_head; ; p = &(*p)->next) {
if (*p == NULL)
Py_FatalError(
"PyThreadState_Delete: invalid tstate");
if (*p == tstate)
break;
/* Sanity check. These states should never happen but if
* they do we must abort. Otherwise we'll end up spinning in
* in a tight loop with the lock held. A similar check is done
* in thread.c find_key(). */
if (*p == prev_p)
Py_FatalError(
"PyThreadState_Delete: small circular list(!)"
" and tstate not found.");
prev_p = *p;
if ((*p)->next == interp->tstate_head)
Py_FatalError(
"PyThreadState_Delete: circular list(!) and"
" tstate not found.");
}
*p = tstate->next;
HEAD_UNLOCK();
free(tstate);
PyInterpreterState *interp;
PyThreadState **p;
PyThreadState *prev_p = NULL;
if (tstate == NULL)
Py_FatalError("PyThreadState_Delete: NULL tstate");
interp = tstate->interp;
if (interp == NULL)
Py_FatalError("PyThreadState_Delete: NULL interp");
HEAD_LOCK();
for (p = &interp->tstate_head; ; p = &(*p)->next) {
if (*p == NULL)
Py_FatalError(
"PyThreadState_Delete: invalid tstate");
if (*p == tstate)
break;
/* Sanity check. These states should never happen but if
* they do we must abort. Otherwise we'll end up spinning in
* in a tight loop with the lock held. A similar check is done
* in thread.c find_key(). */
if (*p == prev_p)
Py_FatalError(
"PyThreadState_Delete: small circular list(!)"
" and tstate not found.");
prev_p = *p;
if ((*p)->next == interp->tstate_head)
Py_FatalError(
"PyThreadState_Delete: circular list(!) and"
" tstate not found.");
}
*p = tstate->next;
HEAD_UNLOCK();
free(tstate);
}
void
PyThreadState_Delete(PyThreadState *tstate)
{
if (tstate == _PyThreadState_Current)
Py_FatalError("PyThreadState_Delete: tstate is still current");
tstate_delete_common(tstate);
if (tstate == _PyThreadState_Current)
Py_FatalError("PyThreadState_Delete: tstate is still current");
tstate_delete_common(tstate);
#ifdef WITH_THREAD
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
#endif /* WITH_THREAD */
}
@ -308,15 +308,15 @@ PyThreadState_Delete(PyThreadState *tstate)
void
PyThreadState_DeleteCurrent()
{
PyThreadState *tstate = _PyThreadState_Current;
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
_PyThreadState_Current = NULL;
tstate_delete_common(tstate);
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
PyEval_ReleaseLock();
PyThreadState *tstate = _PyThreadState_Current;
if (tstate == NULL)
Py_FatalError(
"PyThreadState_DeleteCurrent: no current tstate");
_PyThreadState_Current = NULL;
tstate_delete_common(tstate);
if (autoTLSkey && PyThread_get_key_value(autoTLSkey) == tstate)
PyThread_delete_key_value(autoTLSkey);
PyEval_ReleaseLock();
}
#endif /* WITH_THREAD */
@ -324,36 +324,36 @@ PyThreadState_DeleteCurrent()
PyThreadState *
PyThreadState_Get(void)
{
if (_PyThreadState_Current == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
if (_PyThreadState_Current == NULL)
Py_FatalError("PyThreadState_Get: no current thread");
return _PyThreadState_Current;
return _PyThreadState_Current;
}
PyThreadState *
PyThreadState_Swap(PyThreadState *newts)
{
PyThreadState *oldts = _PyThreadState_Current;
PyThreadState *oldts = _PyThreadState_Current;
_PyThreadState_Current = newts;
/* It should not be possible for more than one thread state
to be used for a thread. Check this the best we can in debug
builds.
*/
_PyThreadState_Current = newts;
/* It should not be possible for more than one thread state
to be used for a thread. Check this the best we can in debug
builds.
*/
#if defined(Py_DEBUG) && defined(WITH_THREAD)
if (newts) {
/* This can be called from PyEval_RestoreThread(). Similar
to it, we need to ensure errno doesn't change.
*/
int err = errno;
PyThreadState *check = PyGILState_GetThisThreadState();
if (check && check->interp == newts->interp && check != newts)
Py_FatalError("Invalid thread state for this thread");
errno = err;
}
if (newts) {
/* This can be called from PyEval_RestoreThread(). Similar
to it, we need to ensure errno doesn't change.
*/
int err = errno;
PyThreadState *check = PyGILState_GetThisThreadState();
if (check && check->interp == newts->interp && check != newts)
Py_FatalError("Invalid thread state for this thread");
errno = err;
}
#endif
return oldts;
return oldts;
}
/* An extension mechanism to store arbitrary additional per-thread state.
@ -365,16 +365,16 @@ PyThreadState_Swap(PyThreadState *newts)
PyObject *
PyThreadState_GetDict(void)
{
if (_PyThreadState_Current == NULL)
return NULL;
if (_PyThreadState_Current == NULL)
return NULL;
if (_PyThreadState_Current->dict == NULL) {
PyObject *d;
_PyThreadState_Current->dict = d = PyDict_New();
if (d == NULL)
PyErr_Clear();
}
return _PyThreadState_Current->dict;
if (_PyThreadState_Current->dict == NULL) {
PyObject *d;
_PyThreadState_Current->dict = d = PyDict_New();
if (d == NULL)
PyErr_Clear();
}
return _PyThreadState_Current->dict;
}
@ -388,36 +388,36 @@ PyThreadState_GetDict(void)
int
PyThreadState_SetAsyncExc(long id, PyObject *exc) {
PyThreadState *tstate = PyThreadState_GET();
PyInterpreterState *interp = tstate->interp;
PyThreadState *p;
PyThreadState *tstate = PyThreadState_GET();
PyInterpreterState *interp = tstate->interp;
PyThreadState *p;
/* Although the GIL is held, a few C API functions can be called
* without the GIL held, and in particular some that create and
* destroy thread and interpreter states. Those can mutate the
* list of thread states we're traversing, so to prevent that we lock
* head_mutex for the duration.
*/
HEAD_LOCK();
for (p = interp->tstate_head; p != NULL; p = p->next) {
if (p->thread_id == id) {
/* Tricky: we need to decref the current value
* (if any) in p->async_exc, but that can in turn
* allow arbitrary Python code to run, including
* perhaps calls to this function. To prevent
* deadlock, we need to release head_mutex before
* the decref.
*/
PyObject *old_exc = p->async_exc;
Py_XINCREF(exc);
p->async_exc = exc;
HEAD_UNLOCK();
Py_XDECREF(old_exc);
return 1;
}
}
HEAD_UNLOCK();
return 0;
/* Although the GIL is held, a few C API functions can be called
* without the GIL held, and in particular some that create and
* destroy thread and interpreter states. Those can mutate the
* list of thread states we're traversing, so to prevent that we lock
* head_mutex for the duration.
*/
HEAD_LOCK();
for (p = interp->tstate_head; p != NULL; p = p->next) {
if (p->thread_id == id) {
/* Tricky: we need to decref the current value
* (if any) in p->async_exc, but that can in turn
* allow arbitrary Python code to run, including
* perhaps calls to this function. To prevent
* deadlock, we need to release head_mutex before
* the decref.
*/
PyObject *old_exc = p->async_exc;
Py_XINCREF(exc);
p->async_exc = exc;
HEAD_UNLOCK();
Py_XDECREF(old_exc);
return 1;
}
}
HEAD_UNLOCK();
return 0;
}
@ -427,22 +427,22 @@ PyThreadState_SetAsyncExc(long id, PyObject *exc) {
PyInterpreterState *
PyInterpreterState_Head(void)
{
return interp_head;
return interp_head;
}
PyInterpreterState *
PyInterpreterState_Next(PyInterpreterState *interp) {
return interp->next;
return interp->next;
}
PyThreadState *
PyInterpreterState_ThreadHead(PyInterpreterState *interp) {
return interp->tstate_head;
return interp->tstate_head;
}
PyThreadState *
PyThreadState_Next(PyThreadState *tstate) {
return tstate->next;
return tstate->next;
}
/* The implementation of sys._current_frames(). This is intended to be
@ -453,44 +453,44 @@ PyThreadState_Next(PyThreadState *tstate) {
PyObject *
_PyThread_CurrentFrames(void)
{
PyObject *result;
PyInterpreterState *i;
PyObject *result;
PyInterpreterState *i;
result = PyDict_New();
if (result == NULL)
return NULL;
result = PyDict_New();
if (result == NULL)
return NULL;
/* for i in all interpreters:
* for t in all of i's thread states:
* if t's frame isn't NULL, map t's id to its frame
* Because these lists can mutute even when the GIL is held, we
* need to grab head_mutex for the duration.
*/
HEAD_LOCK();
for (i = interp_head; i != NULL; i = i->next) {
PyThreadState *t;
for (t = i->tstate_head; t != NULL; t = t->next) {
PyObject *id;
int stat;
struct _frame *frame = t->frame;
if (frame == NULL)
continue;
id = PyInt_FromLong(t->thread_id);
if (id == NULL)
goto Fail;
stat = PyDict_SetItem(result, id, (PyObject *)frame);
Py_DECREF(id);
if (stat < 0)
goto Fail;
}
}
HEAD_UNLOCK();
return result;
/* for i in all interpreters:
* for t in all of i's thread states:
* if t's frame isn't NULL, map t's id to its frame
* Because these lists can mutute even when the GIL is held, we
* need to grab head_mutex for the duration.
*/
HEAD_LOCK();
for (i = interp_head; i != NULL; i = i->next) {
PyThreadState *t;
for (t = i->tstate_head; t != NULL; t = t->next) {
PyObject *id;
int stat;
struct _frame *frame = t->frame;
if (frame == NULL)
continue;
id = PyInt_FromLong(t->thread_id);
if (id == NULL)
goto Fail;
stat = PyDict_SetItem(result, id, (PyObject *)frame);
Py_DECREF(id);
if (stat < 0)
goto Fail;
}
}
HEAD_UNLOCK();
return result;
Fail:
HEAD_UNLOCK();
Py_DECREF(result);
return NULL;
HEAD_UNLOCK();
Py_DECREF(result);
return NULL;
}
/* Python "auto thread state" API. */
@ -507,12 +507,12 @@ _PyThread_CurrentFrames(void)
static int
PyThreadState_IsCurrent(PyThreadState *tstate)
{
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
/* On Windows at least, simple reads and writes to 32 bit values
are atomic.
*/
return tstate == _PyThreadState_Current;
/* Must be the tstate for this thread */
assert(PyGILState_GetThisThreadState()==tstate);
/* On Windows at least, simple reads and writes to 32 bit values
are atomic.
*/
return tstate == _PyThreadState_Current;
}
/* Internal initialization/finalization functions called by
@ -521,21 +521,21 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
void
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
{
assert(i && t); /* must init with valid states */
autoTLSkey = PyThread_create_key();
autoInterpreterState = i;
assert(PyThread_get_key_value(autoTLSkey) == NULL);
assert(t->gilstate_counter == 0);
assert(i && t); /* must init with valid states */
autoTLSkey = PyThread_create_key();
autoInterpreterState = i;
assert(PyThread_get_key_value(autoTLSkey) == NULL);
assert(t->gilstate_counter == 0);
_PyGILState_NoteThreadState(t);
_PyGILState_NoteThreadState(t);
}
void
_PyGILState_Fini(void)
{
PyThread_delete_key(autoTLSkey);
autoTLSkey = 0;
autoInterpreterState = NULL;
PyThread_delete_key(autoTLSkey);
autoTLSkey = 0;
autoInterpreterState = NULL;
}
/* When a thread state is created for a thread by some mechanism other than
@ -546,113 +546,113 @@ _PyGILState_Fini(void)
static void
_PyGILState_NoteThreadState(PyThreadState* tstate)
{
/* If autoTLSkey is 0, this must be the very first threadstate created
in Py_Initialize(). Don't do anything for now (we'll be back here
when _PyGILState_Init is called). */
if (!autoTLSkey)
return;
/* If autoTLSkey is 0, this must be the very first threadstate created
in Py_Initialize(). Don't do anything for now (we'll be back here
when _PyGILState_Init is called). */
if (!autoTLSkey)
return;
/* Stick the thread state for this thread in thread local storage.
/* Stick the thread state for this thread in thread local storage.
The only situation where you can legitimately have more than one
thread state for an OS level thread is when there are multiple
interpreters, when:
The only situation where you can legitimately have more than one
thread state for an OS level thread is when there are multiple
interpreters, when:
a) You shouldn't really be using the PyGILState_ APIs anyway,
and:
a) You shouldn't really be using the PyGILState_ APIs anyway,
and:
b) The slightly odd way PyThread_set_key_value works (see
comments by its implementation) means that the first thread
state created for that given OS level thread will "win",
which seems reasonable behaviour.
*/
if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
Py_FatalError("Couldn't create autoTLSkey mapping");
b) The slightly odd way PyThread_set_key_value works (see
comments by its implementation) means that the first thread
state created for that given OS level thread will "win",
which seems reasonable behaviour.
*/
if (PyThread_set_key_value(autoTLSkey, (void *)tstate) < 0)
Py_FatalError("Couldn't create autoTLSkey mapping");
/* PyGILState_Release must not try to delete this thread state. */
tstate->gilstate_counter = 1;
/* PyGILState_Release must not try to delete this thread state. */
tstate->gilstate_counter = 1;
}
/* The public functions */
PyThreadState *
PyGILState_GetThisThreadState(void)
{
if (autoInterpreterState == NULL || autoTLSkey == 0)
return NULL;
return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
if (autoInterpreterState == NULL || autoTLSkey == 0)
return NULL;
return (PyThreadState *)PyThread_get_key_value(autoTLSkey);
}
PyGILState_STATE
PyGILState_Ensure(void)
{
int current;
PyThreadState *tcur;
/* Note that we do not auto-init Python here - apart from
potential races with 2 threads auto-initializing, pep-311
spells out other issues. Embedders are expected to have
called Py_Initialize() and usually PyEval_InitThreads().
*/
assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
if (tcur == NULL) {
/* Create a new thread state for this thread */
tcur = PyThreadState_New(autoInterpreterState);
if (tcur == NULL)
Py_FatalError("Couldn't create thread-state for new thread");
/* This is our thread state! We'll need to delete it in the
matching call to PyGILState_Release(). */
tcur->gilstate_counter = 0;
current = 0; /* new thread state is never current */
}
else
current = PyThreadState_IsCurrent(tcur);
if (current == 0)
PyEval_RestoreThread(tcur);
/* Update our counter in the thread-state - no need for locks:
- tcur will remain valid as we hold the GIL.
- the counter is safe as we are the only thread "allowed"
to modify this value
*/
++tcur->gilstate_counter;
return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
int current;
PyThreadState *tcur;
/* Note that we do not auto-init Python here - apart from
potential races with 2 threads auto-initializing, pep-311
spells out other issues. Embedders are expected to have
called Py_Initialize() and usually PyEval_InitThreads().
*/
assert(autoInterpreterState); /* Py_Initialize() hasn't been called! */
tcur = (PyThreadState *)PyThread_get_key_value(autoTLSkey);
if (tcur == NULL) {
/* Create a new thread state for this thread */
tcur = PyThreadState_New(autoInterpreterState);
if (tcur == NULL)
Py_FatalError("Couldn't create thread-state for new thread");
/* This is our thread state! We'll need to delete it in the
matching call to PyGILState_Release(). */
tcur->gilstate_counter = 0;
current = 0; /* new thread state is never current */
}
else
current = PyThreadState_IsCurrent(tcur);
if (current == 0)
PyEval_RestoreThread(tcur);
/* Update our counter in the thread-state - no need for locks:
- tcur will remain valid as we hold the GIL.
- the counter is safe as we are the only thread "allowed"
to modify this value
*/
++tcur->gilstate_counter;
return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
}
void
PyGILState_Release(PyGILState_STATE oldstate)
{
PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
autoTLSkey);
if (tcur == NULL)
Py_FatalError("auto-releasing thread-state, "
"but no thread-state for this thread");
/* We must hold the GIL and have our thread state current */
/* XXX - remove the check - the assert should be fine,
but while this is very new (April 2003), the extra check
by release-only users can't hurt.
*/
if (! PyThreadState_IsCurrent(tcur))
Py_FatalError("This thread state must be current when releasing");
assert(PyThreadState_IsCurrent(tcur));
--tcur->gilstate_counter;
assert(tcur->gilstate_counter >= 0); /* illegal counter value */
PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
autoTLSkey);
if (tcur == NULL)
Py_FatalError("auto-releasing thread-state, "
"but no thread-state for this thread");
/* We must hold the GIL and have our thread state current */
/* XXX - remove the check - the assert should be fine,
but while this is very new (April 2003), the extra check
by release-only users can't hurt.
*/
if (! PyThreadState_IsCurrent(tcur))
Py_FatalError("This thread state must be current when releasing");
assert(PyThreadState_IsCurrent(tcur));
--tcur->gilstate_counter;
assert(tcur->gilstate_counter >= 0); /* illegal counter value */
/* If we're going to destroy this thread-state, we must
* clear it while the GIL is held, as destructors may run.
*/
if (tcur->gilstate_counter == 0) {
/* can't have been locked when we created it */
assert(oldstate == PyGILState_UNLOCKED);
PyThreadState_Clear(tcur);
/* Delete the thread-state. Note this releases the GIL too!
* It's vital that the GIL be held here, to avoid shutdown
* races; see bugs 225673 and 1061968 (that nasty bug has a
* habit of coming back).
*/
PyThreadState_DeleteCurrent();
}
/* Release the lock if necessary */
else if (oldstate == PyGILState_UNLOCKED)
PyEval_SaveThread();
/* If we're going to destroy this thread-state, we must
* clear it while the GIL is held, as destructors may run.
*/
if (tcur->gilstate_counter == 0) {
/* can't have been locked when we created it */
assert(oldstate == PyGILState_UNLOCKED);
PyThreadState_Clear(tcur);
/* Delete the thread-state. Note this releases the GIL too!
* It's vital that the GIL be held here, to avoid shutdown
* races; see bugs 225673 and 1061968 (that nasty bug has a
* habit of coming back).
*/
PyThreadState_DeleteCurrent();
}
/* Release the lock if necessary */
else if (oldstate == PyGILState_UNLOCKED)
PyEval_SaveThread();
}
#ifdef __cplusplus

View file

@ -6,21 +6,21 @@
int
PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size)
{
if (size == 0)
return 0;
while ((--size > 0) &&
(tolower((unsigned)*s1) == tolower((unsigned)*s2))) {
if (!*s1++ || !*s2++)
break;
}
return tolower((unsigned)*s1) - tolower((unsigned)*s2);
if (size == 0)
return 0;
while ((--size > 0) &&
(tolower((unsigned)*s1) == tolower((unsigned)*s2))) {
if (!*s1++ || !*s2++)
break;
}
return tolower((unsigned)*s1) - tolower((unsigned)*s2);
}
int
PyOS_mystricmp(const char *s1, const char *s2)
{
while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) {
;
}
return (tolower((unsigned)*s1) - tolower((unsigned)*s2));
while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) {
;
}
return (tolower((unsigned)*s1) - tolower((unsigned)*s2));
}

View file

@ -5,7 +5,7 @@
/* ascii character tests (as opposed to locale tests) */
#define ISSPACE(c) ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
(c) == '\r' || (c) == '\t' || (c) == '\v')
(c) == '\r' || (c) == '\t' || (c) == '\v')
#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
@ -14,7 +14,7 @@
* @nptr: the string to convert to a numeric value.
* @endptr: if non-%NULL, it returns the character after
* the last character used in the conversion.
*
*
* Converts a string to a #gdouble value.
* This function behaves like the standard strtod() function
* does in the C locale. It does this without actually
@ -31,7 +31,7 @@
* stored in %errno. If the correct value would cause underflow,
* zero is returned and %ERANGE is stored in %errno.
* If memory allocation fails, %ENOMEM is stored in %errno.
*
*
* This function resets %errno before calling strtod() so that
* you can reliably detect overflow and underflow.
*
@ -40,151 +40,151 @@
double
PyOS_ascii_strtod(const char *nptr, char **endptr)
{
char *fail_pos;
double val = -1.0;
struct lconv *locale_data;
const char *decimal_point;
size_t decimal_point_len;
const char *p, *decimal_point_pos;
const char *end = NULL; /* Silence gcc */
const char *digits_pos = NULL;
int negate = 0;
char *fail_pos;
double val = -1.0;
struct lconv *locale_data;
const char *decimal_point;
size_t decimal_point_len;
const char *p, *decimal_point_pos;
const char *end = NULL; /* Silence gcc */
const char *digits_pos = NULL;
int negate = 0;
assert(nptr != NULL);
assert(nptr != NULL);
fail_pos = NULL;
fail_pos = NULL;
locale_data = localeconv();
decimal_point = locale_data->decimal_point;
decimal_point_len = strlen(decimal_point);
locale_data = localeconv();
decimal_point = locale_data->decimal_point;
decimal_point_len = strlen(decimal_point);
assert(decimal_point_len != 0);
assert(decimal_point_len != 0);
decimal_point_pos = NULL;
decimal_point_pos = NULL;
/* We process any leading whitespace and the optional sign manually,
then pass the remainder to the system strtod. This ensures that
the result of an underflow has the correct sign. (bug #1725) */
/* We process any leading whitespace and the optional sign manually,
then pass the remainder to the system strtod. This ensures that
the result of an underflow has the correct sign. (bug #1725) */
p = nptr;
/* Skip leading space */
while (ISSPACE(*p))
p++;
p = nptr;
/* Skip leading space */
while (ISSPACE(*p))
p++;
/* Process leading sign, if present */
if (*p == '-') {
negate = 1;
p++;
} else if (*p == '+') {
p++;
}
/* Process leading sign, if present */
if (*p == '-') {
negate = 1;
p++;
} else if (*p == '+') {
p++;
}
/* What's left should begin with a digit, a decimal point, or one of
the letters i, I, n, N. It should not begin with 0x or 0X */
if ((!ISDIGIT(*p) &&
*p != '.' && *p != 'i' && *p != 'I' && *p != 'n' && *p != 'N')
||
(*p == '0' && (p[1] == 'x' || p[1] == 'X')))
{
if (endptr)
*endptr = (char*)nptr;
errno = EINVAL;
return val;
}
digits_pos = p;
/* What's left should begin with a digit, a decimal point, or one of
the letters i, I, n, N. It should not begin with 0x or 0X */
if ((!ISDIGIT(*p) &&
*p != '.' && *p != 'i' && *p != 'I' && *p != 'n' && *p != 'N')
||
(*p == '0' && (p[1] == 'x' || p[1] == 'X')))
{
if (endptr)
*endptr = (char*)nptr;
errno = EINVAL;
return val;
}
digits_pos = p;
if (decimal_point[0] != '.' ||
decimal_point[1] != 0)
{
while (ISDIGIT(*p))
p++;
if (decimal_point[0] != '.' ||
decimal_point[1] != 0)
{
while (ISDIGIT(*p))
p++;
if (*p == '.')
{
decimal_point_pos = p++;
if (*p == '.')
{
decimal_point_pos = p++;
while (ISDIGIT(*p))
p++;
while (ISDIGIT(*p))
p++;
if (*p == 'e' || *p == 'E')
p++;
if (*p == '+' || *p == '-')
p++;
while (ISDIGIT(*p))
p++;
end = p;
}
else if (strncmp(p, decimal_point, decimal_point_len) == 0)
{
/* Python bug #1417699 */
if (endptr)
*endptr = (char*)nptr;
errno = EINVAL;
return val;
}
/* For the other cases, we need not convert the decimal
point */
}
if (*p == 'e' || *p == 'E')
p++;
if (*p == '+' || *p == '-')
p++;
while (ISDIGIT(*p))
p++;
end = p;
}
else if (strncmp(p, decimal_point, decimal_point_len) == 0)
{
/* Python bug #1417699 */
if (endptr)
*endptr = (char*)nptr;
errno = EINVAL;
return val;
}
/* For the other cases, we need not convert the decimal
point */
}
/* Set errno to zero, so that we can distinguish zero results
and underflows */
errno = 0;
/* Set errno to zero, so that we can distinguish zero results
and underflows */
errno = 0;
if (decimal_point_pos)
{
char *copy, *c;
if (decimal_point_pos)
{
char *copy, *c;
/* We need to convert the '.' to the locale specific decimal
point */
copy = (char *)PyMem_MALLOC(end - digits_pos +
1 + decimal_point_len);
if (copy == NULL) {
if (endptr)
*endptr = (char *)nptr;
errno = ENOMEM;
return val;
}
/* We need to convert the '.' to the locale specific decimal
point */
copy = (char *)PyMem_MALLOC(end - digits_pos +
1 + decimal_point_len);
if (copy == NULL) {
if (endptr)
*endptr = (char *)nptr;
errno = ENOMEM;
return val;
}
c = copy;
memcpy(c, digits_pos, decimal_point_pos - digits_pos);
c += decimal_point_pos - digits_pos;
memcpy(c, decimal_point, decimal_point_len);
c += decimal_point_len;
memcpy(c, decimal_point_pos + 1,
end - (decimal_point_pos + 1));
c += end - (decimal_point_pos + 1);
*c = 0;
c = copy;
memcpy(c, digits_pos, decimal_point_pos - digits_pos);
c += decimal_point_pos - digits_pos;
memcpy(c, decimal_point, decimal_point_len);
c += decimal_point_len;
memcpy(c, decimal_point_pos + 1,
end - (decimal_point_pos + 1));
c += end - (decimal_point_pos + 1);
*c = 0;
val = strtod(copy, &fail_pos);
val = strtod(copy, &fail_pos);
if (fail_pos)
{
if (fail_pos > decimal_point_pos)
fail_pos = (char *)digits_pos +
(fail_pos - copy) -
(decimal_point_len - 1);
else
fail_pos = (char *)digits_pos +
(fail_pos - copy);
}
if (fail_pos)
{
if (fail_pos > decimal_point_pos)
fail_pos = (char *)digits_pos +
(fail_pos - copy) -
(decimal_point_len - 1);
else
fail_pos = (char *)digits_pos +
(fail_pos - copy);
}
PyMem_FREE(copy);
PyMem_FREE(copy);
}
else {
val = strtod(digits_pos, &fail_pos);
}
}
else {
val = strtod(digits_pos, &fail_pos);
}
if (fail_pos == digits_pos)
fail_pos = (char *)nptr;
if (fail_pos == digits_pos)
fail_pos = (char *)nptr;
if (negate && fail_pos != nptr)
val = -val;
if (negate && fail_pos != nptr)
val = -val;
if (endptr)
*endptr = fail_pos;
if (endptr)
*endptr = fail_pos;
return val;
return val;
}
/* Given a string that may have a decimal point in the current
@ -193,30 +193,30 @@ PyOS_ascii_strtod(const char *nptr, char **endptr)
Py_LOCAL_INLINE(void)
change_decimal_from_locale_to_dot(char* buffer)
{
struct lconv *locale_data = localeconv();
const char *decimal_point = locale_data->decimal_point;
struct lconv *locale_data = localeconv();
const char *decimal_point = locale_data->decimal_point;
if (decimal_point[0] != '.' || decimal_point[1] != 0) {
size_t decimal_point_len = strlen(decimal_point);
if (decimal_point[0] != '.' || decimal_point[1] != 0) {
size_t decimal_point_len = strlen(decimal_point);
if (*buffer == '+' || *buffer == '-')
buffer++;
while (isdigit(Py_CHARMASK(*buffer)))
buffer++;
if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
*buffer = '.';
buffer++;
if (decimal_point_len > 1) {
/* buffer needs to get smaller */
size_t rest_len = strlen(buffer +
(decimal_point_len - 1));
memmove(buffer,
buffer + (decimal_point_len - 1),
rest_len);
buffer[rest_len] = 0;
}
}
}
if (*buffer == '+' || *buffer == '-')
buffer++;
while (isdigit(Py_CHARMASK(*buffer)))
buffer++;
if (strncmp(buffer, decimal_point, decimal_point_len) == 0) {
*buffer = '.';
buffer++;
if (decimal_point_len > 1) {
/* buffer needs to get smaller */
size_t rest_len = strlen(buffer +
(decimal_point_len - 1));
memmove(buffer,
buffer + (decimal_point_len - 1),
rest_len);
buffer[rest_len] = 0;
}
}
}
}
@ -231,65 +231,65 @@ as necessary to represent the exponent.
Py_LOCAL_INLINE(void)
ensure_minimum_exponent_length(char* buffer, size_t buf_size)
{
char *p = strpbrk(buffer, "eE");
if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
char *start = p + 2;
int exponent_digit_cnt = 0;
int leading_zero_cnt = 0;
int in_leading_zeros = 1;
int significant_digit_cnt;
char *p = strpbrk(buffer, "eE");
if (p && (*(p + 1) == '-' || *(p + 1) == '+')) {
char *start = p + 2;
int exponent_digit_cnt = 0;
int leading_zero_cnt = 0;
int in_leading_zeros = 1;
int significant_digit_cnt;
/* Skip over the exponent and the sign. */
p += 2;
/* Skip over the exponent and the sign. */
p += 2;
/* Find the end of the exponent, keeping track of leading
zeros. */
while (*p && isdigit(Py_CHARMASK(*p))) {
if (in_leading_zeros && *p == '0')
++leading_zero_cnt;
if (*p != '0')
in_leading_zeros = 0;
++p;
++exponent_digit_cnt;
}
/* Find the end of the exponent, keeping track of leading
zeros. */
while (*p && isdigit(Py_CHARMASK(*p))) {
if (in_leading_zeros && *p == '0')
++leading_zero_cnt;
if (*p != '0')
in_leading_zeros = 0;
++p;
++exponent_digit_cnt;
}
significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
/* If there are 2 exactly digits, we're done,
regardless of what they contain */
}
else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
int extra_zeros_cnt;
significant_digit_cnt = exponent_digit_cnt - leading_zero_cnt;
if (exponent_digit_cnt == MIN_EXPONENT_DIGITS) {
/* If there are 2 exactly digits, we're done,
regardless of what they contain */
}
else if (exponent_digit_cnt > MIN_EXPONENT_DIGITS) {
int extra_zeros_cnt;
/* There are more than 2 digits in the exponent. See
if we can delete some of the leading zeros */
if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
significant_digit_cnt = MIN_EXPONENT_DIGITS;
extra_zeros_cnt = exponent_digit_cnt -
significant_digit_cnt;
/* There are more than 2 digits in the exponent. See
if we can delete some of the leading zeros */
if (significant_digit_cnt < MIN_EXPONENT_DIGITS)
significant_digit_cnt = MIN_EXPONENT_DIGITS;
extra_zeros_cnt = exponent_digit_cnt -
significant_digit_cnt;
/* Delete extra_zeros_cnt worth of characters from the
front of the exponent */
assert(extra_zeros_cnt >= 0);
/* Delete extra_zeros_cnt worth of characters from the
front of the exponent */
assert(extra_zeros_cnt >= 0);
/* Add one to significant_digit_cnt to copy the
trailing 0 byte, thus setting the length */
memmove(start,
start + extra_zeros_cnt,
significant_digit_cnt + 1);
}
else {
/* If there are fewer than 2 digits, add zeros
until there are 2, if there's enough room */
int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
if (start + zeros + exponent_digit_cnt + 1
< buffer + buf_size) {
memmove(start + zeros, start,
exponent_digit_cnt + 1);
memset(start, '0', zeros);
}
}
}
/* Add one to significant_digit_cnt to copy the
trailing 0 byte, thus setting the length */
memmove(start,
start + extra_zeros_cnt,
significant_digit_cnt + 1);
}
else {
/* If there are fewer than 2 digits, add zeros
until there are 2, if there's enough room */
int zeros = MIN_EXPONENT_DIGITS - exponent_digit_cnt;
if (start + zeros + exponent_digit_cnt + 1
< buffer + buf_size) {
memmove(start + zeros, start,
exponent_digit_cnt + 1);
memset(start, '0', zeros);
}
}
}
}
/* Ensure that buffer has a decimal point in it. The decimal point
@ -297,48 +297,48 @@ ensure_minimum_exponent_length(char* buffer, size_t buf_size)
Py_LOCAL_INLINE(void)
ensure_decimal_point(char* buffer, size_t buf_size)
{
int insert_count = 0;
char* chars_to_insert;
int insert_count = 0;
char* chars_to_insert;
/* search for the first non-digit character */
char *p = buffer;
if (*p == '-' || *p == '+')
/* Skip leading sign, if present. I think this could only
ever be '-', but it can't hurt to check for both. */
++p;
while (*p && isdigit(Py_CHARMASK(*p)))
++p;
/* search for the first non-digit character */
char *p = buffer;
if (*p == '-' || *p == '+')
/* Skip leading sign, if present. I think this could only
ever be '-', but it can't hurt to check for both. */
++p;
while (*p && isdigit(Py_CHARMASK(*p)))
++p;
if (*p == '.') {
if (isdigit(Py_CHARMASK(*(p+1)))) {
/* Nothing to do, we already have a decimal
point and a digit after it */
}
else {
/* We have a decimal point, but no following
digit. Insert a zero after the decimal. */
++p;
chars_to_insert = "0";
insert_count = 1;
}
}
else {
chars_to_insert = ".0";
insert_count = 2;
}
if (insert_count) {
size_t buf_len = strlen(buffer);
if (buf_len + insert_count + 1 >= buf_size) {
/* If there is not enough room in the buffer
for the additional text, just skip it. It's
not worth generating an error over. */
}
else {
memmove(p + insert_count, p,
buffer + strlen(buffer) - p + 1);
memcpy(p, chars_to_insert, insert_count);
}
}
if (*p == '.') {
if (isdigit(Py_CHARMASK(*(p+1)))) {
/* Nothing to do, we already have a decimal
point and a digit after it */
}
else {
/* We have a decimal point, but no following
digit. Insert a zero after the decimal. */
++p;
chars_to_insert = "0";
insert_count = 1;
}
}
else {
chars_to_insert = ".0";
insert_count = 2;
}
if (insert_count) {
size_t buf_len = strlen(buffer);
if (buf_len + insert_count + 1 >= buf_size) {
/* If there is not enough room in the buffer
for the additional text, just skip it. It's
not worth generating an error over. */
}
else {
memmove(p + insert_count, p,
buffer + strlen(buffer) - p + 1);
memcpy(p, chars_to_insert, insert_count);
}
}
}
/* Add the locale specific grouping characters to buffer. Note
@ -347,29 +347,29 @@ ensure_decimal_point(char* buffer, size_t buf_size)
Py_LOCAL_INLINE(int)
add_thousands_grouping(char* buffer, size_t buf_size)
{
Py_ssize_t len = strlen(buffer);
struct lconv *locale_data = localeconv();
const char *decimal_point = locale_data->decimal_point;
Py_ssize_t len = strlen(buffer);
struct lconv *locale_data = localeconv();
const char *decimal_point = locale_data->decimal_point;
/* Find the decimal point, if any. We're only concerned
about the characters to the left of the decimal when
adding grouping. */
char *p = strstr(buffer, decimal_point);
if (!p) {
/* No decimal, use the entire string. */
/* Find the decimal point, if any. We're only concerned
about the characters to the left of the decimal when
adding grouping. */
char *p = strstr(buffer, decimal_point);
if (!p) {
/* No decimal, use the entire string. */
/* If any exponent, adjust p. */
p = strpbrk(buffer, "eE");
if (!p)
/* No exponent and no decimal. Use the entire
string. */
p = buffer + len;
}
/* At this point, p points just past the right-most character we
want to format. We need to add the grouping string for the
characters between buffer and p. */
return _PyString_InsertThousandsGrouping(buffer, len, p-buffer,
buf_size, NULL, 1);
/* If any exponent, adjust p. */
p = strpbrk(buffer, "eE");
if (!p)
/* No exponent and no decimal. Use the entire
string. */
p = buffer + len;
}
/* At this point, p points just past the right-most character we
want to format. We need to add the grouping string for the
characters between buffer and p. */
return _PyString_InsertThousandsGrouping(buffer, len, p-buffer,
buf_size, NULL, 1);
}
/* see FORMATBUFLEN in unicodeobject.c */
@ -380,14 +380,14 @@ add_thousands_grouping(char* buffer, size_t buf_size)
* @buffer: A buffer to place the resulting string in
* @buf_size: The length of the buffer.
* @format: The printf()-style format to use for the
* code to use for converting.
* code to use for converting.
* @d: The #gdouble to convert
*
* Converts a #gdouble to a string, using the '.' as
* decimal point. To format the number you pass in
* a printf()-style format string. Allowed conversion
* specifiers are 'e', 'E', 'f', 'F', 'g', 'G', and 'n'.
*
*
* 'n' is the same as 'g', except it uses the current locale.
* 'Z' is the same as 'g', except it always has a decimal and
* at least one digit after the decimal.
@ -395,96 +395,96 @@ add_thousands_grouping(char* buffer, size_t buf_size)
* Return value: The pointer to the buffer with the converted string.
**/
char *
PyOS_ascii_formatd(char *buffer,
size_t buf_size,
const char *format,
double d)
PyOS_ascii_formatd(char *buffer,
size_t buf_size,
const char *format,
double d)
{
char format_char;
size_t format_len = strlen(format);
char format_char;
size_t format_len = strlen(format);
/* For type 'n', we need to make a copy of the format string, because
we're going to modify 'n' -> 'g', and format is const char*, so we
can't modify it directly. FLOAT_FORMATBUFLEN should be longer than
we ever need this to be. There's an upcoming check to ensure it's
big enough. */
/* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but
also with at least one character past the decimal. */
char tmp_format[FLOAT_FORMATBUFLEN];
/* For type 'n', we need to make a copy of the format string, because
we're going to modify 'n' -> 'g', and format is const char*, so we
can't modify it directly. FLOAT_FORMATBUFLEN should be longer than
we ever need this to be. There's an upcoming check to ensure it's
big enough. */
/* Issue 2264: code 'Z' requires copying the format. 'Z' is 'g', but
also with at least one character past the decimal. */
char tmp_format[FLOAT_FORMATBUFLEN];
/* The last character in the format string must be the format char */
format_char = format[format_len - 1];
/* The last character in the format string must be the format char */
format_char = format[format_len - 1];
if (format[0] != '%')
return NULL;
if (format[0] != '%')
return NULL;
/* I'm not sure why this test is here. It's ensuring that the format
string after the first character doesn't have a single quote, a
lowercase l, or a percent. This is the reverse of the commented-out
test about 10 lines ago. */
if (strpbrk(format + 1, "'l%"))
return NULL;
/* I'm not sure why this test is here. It's ensuring that the format
string after the first character doesn't have a single quote, a
lowercase l, or a percent. This is the reverse of the commented-out
test about 10 lines ago. */
if (strpbrk(format + 1, "'l%"))
return NULL;
/* Also curious about this function is that it accepts format strings
like "%xg", which are invalid for floats. In general, the
interface to this function is not very good, but changing it is
difficult because it's a public API. */
/* Also curious about this function is that it accepts format strings
like "%xg", which are invalid for floats. In general, the
interface to this function is not very good, but changing it is
difficult because it's a public API. */
if (!(format_char == 'e' || format_char == 'E' ||
format_char == 'f' || format_char == 'F' ||
format_char == 'g' || format_char == 'G' ||
format_char == 'n' || format_char == 'Z'))
return NULL;
if (!(format_char == 'e' || format_char == 'E' ||
format_char == 'f' || format_char == 'F' ||
format_char == 'g' || format_char == 'G' ||
format_char == 'n' || format_char == 'Z'))
return NULL;
/* Map 'n' or 'Z' format_char to 'g', by copying the format string and
replacing the final char with a 'g' */
if (format_char == 'n' || format_char == 'Z') {
if (format_len + 1 >= sizeof(tmp_format)) {
/* The format won't fit in our copy. Error out. In
practice, this will never happen and will be
detected by returning NULL */
return NULL;
}
strcpy(tmp_format, format);
tmp_format[format_len - 1] = 'g';
format = tmp_format;
}
/* Map 'n' or 'Z' format_char to 'g', by copying the format string and
replacing the final char with a 'g' */
if (format_char == 'n' || format_char == 'Z') {
if (format_len + 1 >= sizeof(tmp_format)) {
/* The format won't fit in our copy. Error out. In
practice, this will never happen and will be
detected by returning NULL */
return NULL;
}
strcpy(tmp_format, format);
tmp_format[format_len - 1] = 'g';
format = tmp_format;
}
/* Have PyOS_snprintf do the hard work */
PyOS_snprintf(buffer, buf_size, format, d);
/* Have PyOS_snprintf do the hard work */
PyOS_snprintf(buffer, buf_size, format, d);
/* Do various fixups on the return string */
/* Do various fixups on the return string */
/* Get the current locale, and find the decimal point string.
Convert that string back to a dot. Do not do this if using the
'n' (number) format code, since we want to keep the localized
decimal point in that case. */
if (format_char != 'n')
change_decimal_from_locale_to_dot(buffer);
/* Get the current locale, and find the decimal point string.
Convert that string back to a dot. Do not do this if using the
'n' (number) format code, since we want to keep the localized
decimal point in that case. */
if (format_char != 'n')
change_decimal_from_locale_to_dot(buffer);
/* If an exponent exists, ensure that the exponent is at least
MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
for the extra zeros. Also, if there are more than
MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
back to MIN_EXPONENT_DIGITS */
ensure_minimum_exponent_length(buffer, buf_size);
/* If an exponent exists, ensure that the exponent is at least
MIN_EXPONENT_DIGITS digits, providing the buffer is large enough
for the extra zeros. Also, if there are more than
MIN_EXPONENT_DIGITS, remove as many zeros as possible until we get
back to MIN_EXPONENT_DIGITS */
ensure_minimum_exponent_length(buffer, buf_size);
/* If format_char is 'Z', make sure we have at least one character
after the decimal point (and make sure we have a decimal point). */
if (format_char == 'Z')
ensure_decimal_point(buffer, buf_size);
/* If format_char is 'Z', make sure we have at least one character
after the decimal point (and make sure we have a decimal point). */
if (format_char == 'Z')
ensure_decimal_point(buffer, buf_size);
/* If format_char is 'n', add the thousands grouping. */
if (format_char == 'n')
if (!add_thousands_grouping(buffer, buf_size))
return NULL;
/* If format_char is 'n', add the thousands grouping. */
if (format_char == 'n')
if (!add_thousands_grouping(buffer, buf_size))
return NULL;
return buffer;
return buffer;
}
double
PyOS_ascii_atof(const char *nptr)
{
return PyOS_ascii_strtod(nptr, NULL);
return PyOS_ascii_strtod(nptr, NULL);
}

File diff suppressed because it is too large Load diff

View file

@ -14,7 +14,7 @@
Defines: double strtod (char *str, char**ptr)
*/
/* This is an implementation of the strtod() function described in the
/* This is an implementation of the strtod() function described in the
System V manuals, with a different name to avoid linker problems.
All that str2dbl() does itself is check that the argument is well-formed
and is in range. It leaves the work of conversion to atof(), which is
@ -22,18 +22,18 @@
There are two reasons why this should be provided to the net:
(a) some UNIX systems do not yet have strtod(), or do not have it
available in the BSD "universe" (but they do have atof()).
available in the BSD "universe" (but they do have atof()).
(b) some of the UNIX systems that *do* have it get it wrong.
(some crash with large arguments, some assign the wrong *ptr value).
(some crash with large arguments, some assign the wrong *ptr value).
There is a reason why *we* are providing it: we need a correct version
of strtod(), and if we give this one away maybe someone will look for
mistakes in it and fix them for us (:-).
*/
/* The following constants are machine-specific. MD{MIN,MAX}EXPT are
integers and MD{MIN,MAX}FRAC are strings such that
0.${MDMAXFRAC}e${MDMAXEXPT} is the largest representable double,
0.${MDMINFRAC}e${MDMINEXPT} is the smallest representable +ve double
0.${MDMAXFRAC}e${MDMAXEXPT} is the largest representable double,
0.${MDMINFRAC}e${MDMINEXPT} is the smallest representable +ve double
MD{MIN,MAX}FRAC must not have any trailing zeros.
The values here are for IEEE-754 64-bit floats.
It is not perfectly clear to me whether an IEEE infinity should be
@ -44,113 +44,113 @@
I do know about <values.h>, but the whole point of this file is that
we can't always trust that stuff to be there or to be correct.
*/
static int MDMINEXPT = -323;
static char MDMINFRAC[] = "494065645841246544";
static double ZERO = 0.0;
static int MDMINEXPT = -323;
static char MDMINFRAC[] = "494065645841246544";
static double ZERO = 0.0;
static int MDMAXEXPT = 309;
static char MDMAXFRAC[] = "17976931348623157";
static double HUGE = 1.7976931348623157e308;
static int MDMAXEXPT = 309;
static char MDMAXFRAC[] = "17976931348623157";
static double HUGE = 1.7976931348623157e308;
extern double atof(const char *); /* Only called when result known to be ok */
extern double atof(const char *); /* Only called when result known to be ok */
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
extern int errno;
extern int errno;
double strtod(char *str, char **ptr)
{
int sign, scale, dotseen;
int esign, expt;
char *save;
register char *sp, *dp;
register int c;
char *buforg, *buflim;
char buffer[64]; /* 45-digit significant + */
/* 13-digit exponent */
sp = str;
while (*sp == ' ') sp++;
sign = 1;
if (*sp == '-') sign -= 2, sp++;
dotseen = 0, scale = 0;
dp = buffer;
*dp++ = '0'; *dp++ = '.';
buforg = dp, buflim = buffer+48;
for (save = sp; c = *sp; sp++)
if (c == '.') {
if (dotseen) break;
dotseen++;
} else
if ((unsigned)(c-'0') > (unsigned)('9'-'0')) {
break;
} else
if (c == '0') {
if (dp != buforg) {
/* This is not the first digit, so we want to keep it */
if (dp < buflim) *dp++ = c;
if (!dotseen) scale++;
} else {
/* No non-zero digits seen yet */
/* If a . has been seen, scale must be adjusted */
if (dotseen) scale--;
}
} else {
/* This is a nonzero digit, so we want to keep it */
if (dp < buflim) *dp++ = c;
/* If it precedes a ., scale must be adjusted */
if (!dotseen) scale++;
}
if (sp == save) {
if (ptr) *ptr = str;
errno = EDOM; /* what should this be? */
return ZERO;
}
while (dp > buforg && dp[-1] == '0') --dp;
if (dp == buforg) *dp++ = '0';
*dp = '\0';
/* Now the contents of buffer are
+--+--------+-+--------+
|0.|fraction|\|leftover|
+--+--------+-+--------+
^dp points here
where fraction begins with 0 iff it is "0", and has at most
45 digits in it, and leftover is at least 16 characters.
*/
save = sp, expt = 0, esign = 1;
do {
c = *sp++;
if (c != 'e' && c != 'E') break;
c = *sp++;
if (c == '-') esign -= 2, c = *sp++; else
if (c == '+' /* || c == ' ' */ ) c = *sp++;
if ((unsigned)(c-'0') > (unsigned)('9'-'0')) break;
while (c == '0') c = *sp++;
for (; (unsigned)(c-'0') <= (unsigned)('9'-'0'); c = *sp++)
expt = expt*10 + c-'0';
if (esign < 0) expt = -expt;
save = sp-1;
} while (0);
if (ptr) *ptr = save;
expt += scale;
/* Now the number is sign*0.fraction*10**expt */
errno = ERANGE;
if (expt > MDMAXEXPT) {
return HUGE*sign;
} else
if (expt == MDMAXEXPT) {
if (strcmp(buforg, MDMAXFRAC) > 0) return HUGE*sign;
} else
if (expt < MDMINEXPT) {
return ZERO*sign;
} else
if (expt == MDMINEXPT) {
if (strcmp(buforg, MDMINFRAC) < 0) return ZERO*sign;
}
/* We have now established that the number can be */
/* represented without overflow or underflow */
(void) sprintf(dp, "E%d", expt);
errno = 0;
return atof(buffer)*sign;
int sign, scale, dotseen;
int esign, expt;
char *save;
register char *sp, *dp;
register int c;
char *buforg, *buflim;
char buffer[64]; /* 45-digit significant + */
/* 13-digit exponent */
sp = str;
while (*sp == ' ') sp++;
sign = 1;
if (*sp == '-') sign -= 2, sp++;
dotseen = 0, scale = 0;
dp = buffer;
*dp++ = '0'; *dp++ = '.';
buforg = dp, buflim = buffer+48;
for (save = sp; c = *sp; sp++)
if (c == '.') {
if (dotseen) break;
dotseen++;
} else
if ((unsigned)(c-'0') > (unsigned)('9'-'0')) {
break;
} else
if (c == '0') {
if (dp != buforg) {
/* This is not the first digit, so we want to keep it */
if (dp < buflim) *dp++ = c;
if (!dotseen) scale++;
} else {
/* No non-zero digits seen yet */
/* If a . has been seen, scale must be adjusted */
if (dotseen) scale--;
}
} else {
/* This is a nonzero digit, so we want to keep it */
if (dp < buflim) *dp++ = c;
/* If it precedes a ., scale must be adjusted */
if (!dotseen) scale++;
}
if (sp == save) {
if (ptr) *ptr = str;
errno = EDOM; /* what should this be? */
return ZERO;
}
while (dp > buforg && dp[-1] == '0') --dp;
if (dp == buforg) *dp++ = '0';
*dp = '\0';
/* Now the contents of buffer are
+--+--------+-+--------+
|0.|fraction|\|leftover|
+--+--------+-+--------+
^dp points here
where fraction begins with 0 iff it is "0", and has at most
45 digits in it, and leftover is at least 16 characters.
*/
save = sp, expt = 0, esign = 1;
do {
c = *sp++;
if (c != 'e' && c != 'E') break;
c = *sp++;
if (c == '-') esign -= 2, c = *sp++; else
if (c == '+' /* || c == ' ' */ ) c = *sp++;
if ((unsigned)(c-'0') > (unsigned)('9'-'0')) break;
while (c == '0') c = *sp++;
for (; (unsigned)(c-'0') <= (unsigned)('9'-'0'); c = *sp++)
expt = expt*10 + c-'0';
if (esign < 0) expt = -expt;
save = sp-1;
} while (0);
if (ptr) *ptr = save;
expt += scale;
/* Now the number is sign*0.fraction*10**expt */
errno = ERANGE;
if (expt > MDMAXEXPT) {
return HUGE*sign;
} else
if (expt == MDMAXEXPT) {
if (strcmp(buforg, MDMAXFRAC) > 0) return HUGE*sign;
} else
if (expt < MDMINEXPT) {
return ZERO*sign;
} else
if (expt == MDMINEXPT) {
if (strcmp(buforg, MDMINFRAC) < 0) return ZERO*sign;
}
/* We have now established that the number can be */
/* represented without overflow or underflow */
(void) sprintf(dp, "E%d", expt);
errno = 0;
return atof(buffer)*sign;
}

View file

@ -8,355 +8,355 @@
static PyObject *
listmembers(struct memberlist *mlist)
{
int i, n;
PyObject *v;
for (n = 0; mlist[n].name != NULL; n++)
;
v = PyList_New(n);
if (v != NULL) {
for (i = 0; i < n; i++)
PyList_SetItem(v, i,
PyString_FromString(mlist[i].name));
if (PyErr_Occurred()) {
Py_DECREF(v);
v = NULL;
}
else {
PyList_Sort(v);
}
}
return v;
int i, n;
PyObject *v;
for (n = 0; mlist[n].name != NULL; n++)
;
v = PyList_New(n);
if (v != NULL) {
for (i = 0; i < n; i++)
PyList_SetItem(v, i,
PyString_FromString(mlist[i].name));
if (PyErr_Occurred()) {
Py_DECREF(v);
v = NULL;
}
else {
PyList_Sort(v);
}
}
return v;
}
PyObject *
PyMember_Get(const char *addr, struct memberlist *mlist, const char *name)
{
struct memberlist *l;
struct memberlist *l;
if (strcmp(name, "__members__") == 0)
return listmembers(mlist);
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
PyMemberDef copy;
copy.name = l->name;
copy.type = l->type;
copy.offset = l->offset;
copy.flags = l->flags;
copy.doc = NULL;
return PyMember_GetOne(addr, &copy);
}
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
if (strcmp(name, "__members__") == 0)
return listmembers(mlist);
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
PyMemberDef copy;
copy.name = l->name;
copy.type = l->type;
copy.offset = l->offset;
copy.flags = l->flags;
copy.doc = NULL;
return PyMember_GetOne(addr, &copy);
}
}
PyErr_SetString(PyExc_AttributeError, name);
return NULL;
}
PyObject *
PyMember_GetOne(const char *addr, PyMemberDef *l)
{
PyObject *v;
if ((l->flags & READ_RESTRICTED) &&
PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
return NULL;
}
addr += l->offset;
switch (l->type) {
case T_BOOL:
v = PyBool_FromLong(*(char*)addr);
break;
case T_BYTE:
v = PyInt_FromLong(*(char*)addr);
break;
case T_UBYTE:
v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
break;
case T_SHORT:
v = PyInt_FromLong(*(short*)addr);
break;
case T_USHORT:
v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
break;
case T_INT:
v = PyInt_FromLong(*(int*)addr);
break;
case T_UINT:
v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
break;
case T_LONG:
v = PyInt_FromLong(*(long*)addr);
break;
case T_ULONG:
v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
break;
case T_PYSSIZET:
v = PyInt_FromSsize_t(*(Py_ssize_t*)addr);
break;
case T_FLOAT:
v = PyFloat_FromDouble((double)*(float*)addr);
break;
case T_DOUBLE:
v = PyFloat_FromDouble(*(double*)addr);
break;
case T_STRING:
if (*(char**)addr == NULL) {
Py_INCREF(Py_None);
v = Py_None;
}
else
v = PyString_FromString(*(char**)addr);
break;
case T_STRING_INPLACE:
v = PyString_FromString((char*)addr);
break;
case T_CHAR:
v = PyString_FromStringAndSize((char*)addr, 1);
break;
case T_OBJECT:
v = *(PyObject **)addr;
if (v == NULL)
v = Py_None;
Py_INCREF(v);
break;
case T_OBJECT_EX:
v = *(PyObject **)addr;
if (v == NULL)
PyErr_SetString(PyExc_AttributeError, l->name);
Py_XINCREF(v);
break;
PyObject *v;
if ((l->flags & READ_RESTRICTED) &&
PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
return NULL;
}
addr += l->offset;
switch (l->type) {
case T_BOOL:
v = PyBool_FromLong(*(char*)addr);
break;
case T_BYTE:
v = PyInt_FromLong(*(char*)addr);
break;
case T_UBYTE:
v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
break;
case T_SHORT:
v = PyInt_FromLong(*(short*)addr);
break;
case T_USHORT:
v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
break;
case T_INT:
v = PyInt_FromLong(*(int*)addr);
break;
case T_UINT:
v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
break;
case T_LONG:
v = PyInt_FromLong(*(long*)addr);
break;
case T_ULONG:
v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
break;
case T_PYSSIZET:
v = PyInt_FromSsize_t(*(Py_ssize_t*)addr);
break;
case T_FLOAT:
v = PyFloat_FromDouble((double)*(float*)addr);
break;
case T_DOUBLE:
v = PyFloat_FromDouble(*(double*)addr);
break;
case T_STRING:
if (*(char**)addr == NULL) {
Py_INCREF(Py_None);
v = Py_None;
}
else
v = PyString_FromString(*(char**)addr);
break;
case T_STRING_INPLACE:
v = PyString_FromString((char*)addr);
break;
case T_CHAR:
v = PyString_FromStringAndSize((char*)addr, 1);
break;
case T_OBJECT:
v = *(PyObject **)addr;
if (v == NULL)
v = Py_None;
Py_INCREF(v);
break;
case T_OBJECT_EX:
v = *(PyObject **)addr;
if (v == NULL)
PyErr_SetString(PyExc_AttributeError, l->name);
Py_XINCREF(v);
break;
#ifdef HAVE_LONG_LONG
case T_LONGLONG:
v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
break;
case T_ULONGLONG:
v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
break;
case T_LONGLONG:
v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
break;
case T_ULONGLONG:
v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
break;
#endif /* HAVE_LONG_LONG */
default:
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
v = NULL;
}
return v;
default:
PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
v = NULL;
}
return v;
}
int
PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v)
{
struct memberlist *l;
struct memberlist *l;
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
PyMemberDef copy;
copy.name = l->name;
copy.type = l->type;
copy.offset = l->offset;
copy.flags = l->flags;
copy.doc = NULL;
return PyMember_SetOne(addr, &copy, v);
}
}
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
PyMemberDef copy;
copy.name = l->name;
copy.type = l->type;
copy.offset = l->offset;
copy.flags = l->flags;
copy.doc = NULL;
return PyMember_SetOne(addr, &copy, v);
}
}
PyErr_SetString(PyExc_AttributeError, name);
return -1;
PyErr_SetString(PyExc_AttributeError, name);
return -1;
}
#define WARN(msg) \
do { \
if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
return -1; \
#define WARN(msg) \
do { \
if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0) \
return -1; \
} while (0)
int
PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
{
PyObject *oldv;
PyObject *oldv;
addr += l->offset;
addr += l->offset;
if ((l->flags & READONLY))
{
PyErr_SetString(PyExc_TypeError, "readonly attribute");
return -1;
}
if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
return -1;
}
if (v == NULL) {
if (l->type == T_OBJECT_EX) {
/* Check if the attribute is set. */
if (*(PyObject **)addr == NULL) {
PyErr_SetString(PyExc_AttributeError, l->name);
return -1;
}
}
else if (l->type != T_OBJECT) {
PyErr_SetString(PyExc_TypeError,
"can't delete numeric/char attribute");
return -1;
}
}
switch (l->type) {
case T_BOOL:{
if (!PyBool_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"attribute value type must be bool");
return -1;
}
if (v == Py_True)
*(char*)addr = (char) 1;
else
*(char*)addr = (char) 0;
break;
}
case T_BYTE:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(char*)addr = (char)long_val;
/* XXX: For compatibility, only warn about truncations
for now. */
if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
WARN("Truncation of value to char");
break;
}
case T_UBYTE:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(unsigned char*)addr = (unsigned char)long_val;
if ((long_val > UCHAR_MAX) || (long_val < 0))
WARN("Truncation of value to unsigned char");
break;
}
case T_SHORT:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(short*)addr = (short)long_val;
if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
WARN("Truncation of value to short");
break;
}
case T_USHORT:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(unsigned short*)addr = (unsigned short)long_val;
if ((long_val > USHRT_MAX) || (long_val < 0))
WARN("Truncation of value to unsigned short");
break;
}
case T_INT:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(int *)addr = (int)long_val;
if ((long_val > INT_MAX) || (long_val < INT_MIN))
WARN("Truncation of value to int");
break;
}
case T_UINT:{
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
ulong_val = PyLong_AsLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
return -1;
*(unsigned int *)addr = (unsigned int)ulong_val;
WARN("Writing negative value into unsigned field");
} else
*(unsigned int *)addr = (unsigned int)ulong_val;
if (ulong_val > UINT_MAX)
WARN("Truncation of value to unsigned int");
break;
}
case T_LONG:{
*(long*)addr = PyLong_AsLong(v);
if ((*(long*)addr == -1) && PyErr_Occurred())
return -1;
break;
}
case T_ULONG:{
*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
if ((*(unsigned long*)addr == (unsigned long)-1)
&& PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
*(unsigned long*)addr = PyLong_AsLong(v);
if ((*(unsigned long*)addr == (unsigned int)-1)
&& PyErr_Occurred())
return -1;
WARN("Writing negative value into unsigned field");
}
break;
}
case T_PYSSIZET:{
*(Py_ssize_t*)addr = PyInt_AsSsize_t(v);
if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
&& PyErr_Occurred())
return -1;
break;
}
case T_FLOAT:{
double double_val = PyFloat_AsDouble(v);
if ((double_val == -1) && PyErr_Occurred())
return -1;
*(float*)addr = (float)double_val;
break;
}
case T_DOUBLE:
*(double*)addr = PyFloat_AsDouble(v);
if ((*(double*)addr == -1) && PyErr_Occurred())
return -1;
break;
case T_OBJECT:
case T_OBJECT_EX:
Py_XINCREF(v);
oldv = *(PyObject **)addr;
*(PyObject **)addr = v;
Py_XDECREF(oldv);
break;
case T_CHAR:
if (PyString_Check(v) && PyString_Size(v) == 1) {
*(char*)addr = PyString_AsString(v)[0];
}
else {
PyErr_BadArgument();
return -1;
}
break;
case T_STRING:
case T_STRING_INPLACE:
PyErr_SetString(PyExc_TypeError, "readonly attribute");
return -1;
if ((l->flags & READONLY))
{
PyErr_SetString(PyExc_TypeError, "readonly attribute");
return -1;
}
if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
return -1;
}
if (v == NULL) {
if (l->type == T_OBJECT_EX) {
/* Check if the attribute is set. */
if (*(PyObject **)addr == NULL) {
PyErr_SetString(PyExc_AttributeError, l->name);
return -1;
}
}
else if (l->type != T_OBJECT) {
PyErr_SetString(PyExc_TypeError,
"can't delete numeric/char attribute");
return -1;
}
}
switch (l->type) {
case T_BOOL:{
if (!PyBool_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"attribute value type must be bool");
return -1;
}
if (v == Py_True)
*(char*)addr = (char) 1;
else
*(char*)addr = (char) 0;
break;
}
case T_BYTE:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(char*)addr = (char)long_val;
/* XXX: For compatibility, only warn about truncations
for now. */
if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
WARN("Truncation of value to char");
break;
}
case T_UBYTE:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(unsigned char*)addr = (unsigned char)long_val;
if ((long_val > UCHAR_MAX) || (long_val < 0))
WARN("Truncation of value to unsigned char");
break;
}
case T_SHORT:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(short*)addr = (short)long_val;
if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
WARN("Truncation of value to short");
break;
}
case T_USHORT:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(unsigned short*)addr = (unsigned short)long_val;
if ((long_val > USHRT_MAX) || (long_val < 0))
WARN("Truncation of value to unsigned short");
break;
}
case T_INT:{
long long_val = PyInt_AsLong(v);
if ((long_val == -1) && PyErr_Occurred())
return -1;
*(int *)addr = (int)long_val;
if ((long_val > INT_MAX) || (long_val < INT_MIN))
WARN("Truncation of value to int");
break;
}
case T_UINT:{
unsigned long ulong_val = PyLong_AsUnsignedLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
ulong_val = PyLong_AsLong(v);
if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
return -1;
*(unsigned int *)addr = (unsigned int)ulong_val;
WARN("Writing negative value into unsigned field");
} else
*(unsigned int *)addr = (unsigned int)ulong_val;
if (ulong_val > UINT_MAX)
WARN("Truncation of value to unsigned int");
break;
}
case T_LONG:{
*(long*)addr = PyLong_AsLong(v);
if ((*(long*)addr == -1) && PyErr_Occurred())
return -1;
break;
}
case T_ULONG:{
*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
if ((*(unsigned long*)addr == (unsigned long)-1)
&& PyErr_Occurred()) {
/* XXX: For compatibility, accept negative int values
as well. */
PyErr_Clear();
*(unsigned long*)addr = PyLong_AsLong(v);
if ((*(unsigned long*)addr == (unsigned int)-1)
&& PyErr_Occurred())
return -1;
WARN("Writing negative value into unsigned field");
}
break;
}
case T_PYSSIZET:{
*(Py_ssize_t*)addr = PyInt_AsSsize_t(v);
if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
&& PyErr_Occurred())
return -1;
break;
}
case T_FLOAT:{
double double_val = PyFloat_AsDouble(v);
if ((double_val == -1) && PyErr_Occurred())
return -1;
*(float*)addr = (float)double_val;
break;
}
case T_DOUBLE:
*(double*)addr = PyFloat_AsDouble(v);
if ((*(double*)addr == -1) && PyErr_Occurred())
return -1;
break;
case T_OBJECT:
case T_OBJECT_EX:
Py_XINCREF(v);
oldv = *(PyObject **)addr;
*(PyObject **)addr = v;
Py_XDECREF(oldv);
break;
case T_CHAR:
if (PyString_Check(v) && PyString_Size(v) == 1) {
*(char*)addr = PyString_AsString(v)[0];
}
else {
PyErr_BadArgument();
return -1;
}
break;
case T_STRING:
case T_STRING_INPLACE:
PyErr_SetString(PyExc_TypeError, "readonly attribute");
return -1;
#ifdef HAVE_LONG_LONG
case T_LONGLONG:{
PY_LONG_LONG value;
*(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
if ((value == -1) && PyErr_Occurred())
return -1;
break;
}
case T_ULONGLONG:{
unsigned PY_LONG_LONG value;
/* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
doesn't ??? */
if (PyLong_Check(v))
*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
else
*(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
return -1;
break;
}
case T_LONGLONG:{
PY_LONG_LONG value;
*(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
if ((value == -1) && PyErr_Occurred())
return -1;
break;
}
case T_ULONGLONG:{
unsigned PY_LONG_LONG value;
/* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
doesn't ??? */
if (PyLong_Check(v))
*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
else
*(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
return -1;
break;
}
#endif /* HAVE_LONG_LONG */
default:
PyErr_Format(PyExc_SystemError,
"bad memberdescr type for %s", l->name);
return -1;
}
return 0;
default:
PyErr_Format(PyExc_SystemError,
"bad memberdescr type for %s", l->name);
return -1;
}
return 0;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -46,7 +46,7 @@
#endif
/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
enough of the Posix threads package is implimented to support python
enough of the Posix threads package is implimented to support python
threads.
This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
@ -64,8 +64,8 @@
#ifdef Py_DEBUG
static int thread_debug = 0;
#define dprintf(args) (void)((thread_debug & 1) && printf args)
#define d2printf(args) ((thread_debug & 8) && printf args)
#define dprintf(args) (void)((thread_debug & 1) && printf args)
#define d2printf(args) ((thread_debug & 8) && printf args)
#else
#define dprintf(args)
#define d2printf(args)
@ -79,20 +79,20 @@ void
PyThread_init_thread(void)
{
#ifdef Py_DEBUG
char *p = Py_GETENV("PYTHONTHREADDEBUG");
char *p = Py_GETENV("PYTHONTHREADDEBUG");
if (p) {
if (*p)
thread_debug = atoi(p);
else
thread_debug = 1;
}
if (p) {
if (*p)
thread_debug = atoi(p);
else
thread_debug = 1;
}
#endif /* Py_DEBUG */
if (initialized)
return;
initialized = 1;
dprintf(("PyThread_init_thread called\n"));
PyThread__init_thread();
if (initialized)
return;
initialized = 1;
dprintf(("PyThread_init_thread called\n"));
PyThread__init_thread();
}
/* Support for runtime thread stack size tuning.
@ -159,21 +159,21 @@ static size_t _pythread_stacksize = 0;
size_t
PyThread_get_stacksize(void)
{
return _pythread_stacksize;
return _pythread_stacksize;
}
/* Only platforms defining a THREAD_SET_STACKSIZE() macro
in thread_<platform>.h support changing the stack size.
Return 0 if stack size is valid,
-1 if stack size value is invalid,
-2 if setting stack size is not supported. */
-1 if stack size value is invalid,
-2 if setting stack size is not supported. */
int
PyThread_set_stacksize(size_t size)
{
#if defined(THREAD_SET_STACKSIZE)
return THREAD_SET_STACKSIZE(size);
return THREAD_SET_STACKSIZE(size);
#else
return -2;
return -2;
#endif
}
@ -225,15 +225,15 @@ that calls to PyThread_create_key() are serialized externally.
* to enforce exclusion internally.
*/
struct key {
/* Next record in the list, or NULL if this is the last record. */
struct key *next;
/* Next record in the list, or NULL if this is the last record. */
struct key *next;
/* The thread id, according to PyThread_get_thread_ident(). */
long id;
/* The thread id, according to PyThread_get_thread_ident(). */
long id;
/* The key and its associated value. */
int key;
void *value;
/* The key and its associated value. */
int key;
void *value;
};
static struct key *keyhead = NULL;
@ -264,41 +264,41 @@ static int nkeys = 0; /* PyThread_create_key() hands out nkeys+1 next */
static struct key *
find_key(int key, void *value)
{
struct key *p, *prev_p;
long id = PyThread_get_thread_ident();
struct key *p, *prev_p;
long id = PyThread_get_thread_ident();
if (!keymutex)
return NULL;
PyThread_acquire_lock(keymutex, 1);
prev_p = NULL;
for (p = keyhead; p != NULL; p = p->next) {
if (p->id == id && p->key == key)
goto Done;
/* Sanity check. These states should never happen but if
* they do we must abort. Otherwise we'll end up spinning in
* in a tight loop with the lock held. A similar check is done
* in pystate.c tstate_delete_common(). */
if (p == prev_p)
Py_FatalError("tls find_key: small circular list(!)");
prev_p = p;
if (p->next == keyhead)
Py_FatalError("tls find_key: circular list(!)");
}
if (value == NULL) {
assert(p == NULL);
goto Done;
}
p = (struct key *)malloc(sizeof(struct key));
if (p != NULL) {
p->id = id;
p->key = key;
p->value = value;
p->next = keyhead;
keyhead = p;
}
if (!keymutex)
return NULL;
PyThread_acquire_lock(keymutex, 1);
prev_p = NULL;
for (p = keyhead; p != NULL; p = p->next) {
if (p->id == id && p->key == key)
goto Done;
/* Sanity check. These states should never happen but if
* they do we must abort. Otherwise we'll end up spinning in
* in a tight loop with the lock held. A similar check is done
* in pystate.c tstate_delete_common(). */
if (p == prev_p)
Py_FatalError("tls find_key: small circular list(!)");
prev_p = p;
if (p->next == keyhead)
Py_FatalError("tls find_key: circular list(!)");
}
if (value == NULL) {
assert(p == NULL);
goto Done;
}
p = (struct key *)malloc(sizeof(struct key));
if (p != NULL) {
p->id = id;
p->key = key;
p->value = value;
p->next = keyhead;
keyhead = p;
}
Done:
PyThread_release_lock(keymutex);
return p;
PyThread_release_lock(keymutex);
return p;
}
/* Return a new key. This must be called before any other functions in
@ -308,32 +308,32 @@ find_key(int key, void *value)
int
PyThread_create_key(void)
{
/* All parts of this function are wrong if it's called by multiple
* threads simultaneously.
*/
if (keymutex == NULL)
keymutex = PyThread_allocate_lock();
return ++nkeys;
/* All parts of this function are wrong if it's called by multiple
* threads simultaneously.
*/
if (keymutex == NULL)
keymutex = PyThread_allocate_lock();
return ++nkeys;
}
/* Forget the associations for key across *all* threads. */
void
PyThread_delete_key(int key)
{
struct key *p, **q;
struct key *p, **q;
PyThread_acquire_lock(keymutex, 1);
q = &keyhead;
while ((p = *q) != NULL) {
if (p->key == key) {
*q = p->next;
free((void *)p);
/* NB This does *not* free p->value! */
}
else
q = &p->next;
}
PyThread_release_lock(keymutex);
PyThread_acquire_lock(keymutex, 1);
q = &keyhead;
while ((p = *q) != NULL) {
if (p->key == key) {
*q = p->next;
free((void *)p);
/* NB This does *not* free p->value! */
}
else
q = &p->next;
}
PyThread_release_lock(keymutex);
}
/* Confusing: If the current thread has an association for key,
@ -345,14 +345,14 @@ PyThread_delete_key(int key)
int
PyThread_set_key_value(int key, void *value)
{
struct key *p;
struct key *p;
assert(value != NULL);
p = find_key(key, value);
if (p == NULL)
return -1;
else
return 0;
assert(value != NULL);
p = find_key(key, value);
if (p == NULL)
return -1;
else
return 0;
}
/* Retrieve the value associated with key in the current thread, or NULL
@ -361,34 +361,34 @@ PyThread_set_key_value(int key, void *value)
void *
PyThread_get_key_value(int key)
{
struct key *p = find_key(key, NULL);
struct key *p = find_key(key, NULL);
if (p == NULL)
return NULL;
else
return p->value;
if (p == NULL)
return NULL;
else
return p->value;
}
/* Forget the current thread's association for key, if any. */
void
PyThread_delete_key_value(int key)
{
long id = PyThread_get_thread_ident();
struct key *p, **q;
long id = PyThread_get_thread_ident();
struct key *p, **q;
PyThread_acquire_lock(keymutex, 1);
q = &keyhead;
while ((p = *q) != NULL) {
if (p->key == key && p->id == id) {
*q = p->next;
free((void *)p);
/* NB This does *not* free p->value! */
break;
}
else
q = &p->next;
}
PyThread_release_lock(keymutex);
PyThread_acquire_lock(keymutex, 1);
q = &keyhead;
while ((p = *q) != NULL) {
if (p->key == key && p->id == id) {
*q = p->next;
free((void *)p);
/* NB This does *not* free p->value! */
break;
}
else
q = &p->next;
}
PyThread_release_lock(keymutex);
}
/* Forget everything not associated with the current thread id.
@ -399,27 +399,27 @@ PyThread_delete_key_value(int key)
void
PyThread_ReInitTLS(void)
{
long id = PyThread_get_thread_ident();
struct key *p, **q;
long id = PyThread_get_thread_ident();
struct key *p, **q;
if (!keymutex)
return;
/* As with interpreter_lock in PyEval_ReInitThreads()
we just create a new lock without freeing the old one */
keymutex = PyThread_allocate_lock();
if (!keymutex)
return;
/* Delete all keys which do not match the current thread id */
q = &keyhead;
while ((p = *q) != NULL) {
if (p->id != id) {
*q = p->next;
free((void *)p);
/* NB This does *not* free p->value! */
}
else
q = &p->next;
}
/* As with interpreter_lock in PyEval_ReInitThreads()
we just create a new lock without freeing the old one */
keymutex = PyThread_allocate_lock();
/* Delete all keys which do not match the current thread id */
q = &keyhead;
while ((p = *q) != NULL) {
if (p->id != id) {
*q = p->next;
free((void *)p);
/* NB This does *not* free p->value! */
}
else
q = &p->next;
}
}
#endif /* Py_HAVE_NATIVE_TLS */

View file

@ -19,8 +19,8 @@ extern int exit_thread(int);
/* Use an atomic counter and a semaphore for maximum speed. */
typedef struct fastmutex {
sem_id sem;
atomic_t count;
sem_id sem;
atomic_t count;
} fastmutex_t;
@ -33,49 +33,49 @@ static int fastmutex_unlock(fastmutex_t * mutex);
static int fastmutex_create(const char *name, fastmutex_t * mutex)
{
mutex->count = 0;
mutex->sem = create_semaphore(name, 0, 0);
return (mutex->sem < 0) ? -1 : 0;
mutex->count = 0;
mutex->sem = create_semaphore(name, 0, 0);
return (mutex->sem < 0) ? -1 : 0;
}
static int fastmutex_destroy(fastmutex_t * mutex)
{
if (fastmutex_timedlock(mutex, 0) == 0 || errno == EWOULDBLOCK) {
return delete_semaphore(mutex->sem);
}
return 0;
if (fastmutex_timedlock(mutex, 0) == 0 || errno == EWOULDBLOCK) {
return delete_semaphore(mutex->sem);
}
return 0;
}
static int fastmutex_lock(fastmutex_t * mutex)
{
atomic_t prev = atomic_add(&mutex->count, 1);
if (prev > 0)
return lock_semaphore(mutex->sem);
return 0;
atomic_t prev = atomic_add(&mutex->count, 1);
if (prev > 0)
return lock_semaphore(mutex->sem);
return 0;
}
static int fastmutex_timedlock(fastmutex_t * mutex, bigtime_t timeout)
{
atomic_t prev = atomic_add(&mutex->count, 1);
if (prev > 0)
return lock_semaphore_x(mutex->sem, 1, 0, timeout);
return 0;
atomic_t prev = atomic_add(&mutex->count, 1);
if (prev > 0)
return lock_semaphore_x(mutex->sem, 1, 0, timeout);
return 0;
}
static int fastmutex_unlock(fastmutex_t * mutex)
{
atomic_t prev = atomic_add(&mutex->count, -1);
if (prev > 1)
return unlock_semaphore(mutex->sem);
return 0;
atomic_t prev = atomic_add(&mutex->count, -1);
if (prev > 1)
return unlock_semaphore(mutex->sem);
return 0;
}
#endif /* FASTLOCK */
#endif /* FASTLOCK */
/*
@ -84,8 +84,8 @@ static int fastmutex_unlock(fastmutex_t * mutex)
*/
static void PyThread__init_thread(void)
{
/* Do nothing. */
return;
/* Do nothing. */
return;
}
@ -98,90 +98,90 @@ static atomic_t thread_count = 0;
long PyThread_start_new_thread(void (*func) (void *), void *arg)
{
status_t success = -1;
thread_id tid;
char name[OS_NAME_LENGTH];
atomic_t this_thread;
status_t success = -1;
thread_id tid;
char name[OS_NAME_LENGTH];
atomic_t this_thread;
dprintf(("PyThread_start_new_thread called\n"));
dprintf(("PyThread_start_new_thread called\n"));
this_thread = atomic_add(&thread_count, 1);
PyOS_snprintf(name, sizeof(name), "python thread (%d)", this_thread);
this_thread = atomic_add(&thread_count, 1);
PyOS_snprintf(name, sizeof(name), "python thread (%d)", this_thread);
tid = spawn_thread(name, func, NORMAL_PRIORITY, 0, arg);
if (tid < 0) {
dprintf(("PyThread_start_new_thread spawn_thread failed: %s\n", strerror(errno)));
} else {
success = resume_thread(tid);
if (success < 0) {
dprintf(("PyThread_start_new_thread resume_thread failed: %s\n", strerror(errno)));
}
}
tid = spawn_thread(name, func, NORMAL_PRIORITY, 0, arg);
if (tid < 0) {
dprintf(("PyThread_start_new_thread spawn_thread failed: %s\n", strerror(errno)));
} else {
success = resume_thread(tid);
if (success < 0) {
dprintf(("PyThread_start_new_thread resume_thread failed: %s\n", strerror(errno)));
}
}
return (success < 0 ? -1 : tid);
return (success < 0 ? -1 : tid);
}
long PyThread_get_thread_ident(void)
{
return get_thread_id(NULL);
return get_thread_id(NULL);
}
static void do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
dprintf(("PyThread_exit_thread called\n"));
/* Thread-safe way to read a variable without a mutex: */
if (atomic_add(&thread_count, 0) == 0) {
/* No threads around, so exit main(). */
if (no_cleanup)
_exit(0);
else
exit(0);
} else {
/* We're a thread */
exit_thread(0);
}
/* Thread-safe way to read a variable without a mutex: */
if (atomic_add(&thread_count, 0) == 0) {
/* No threads around, so exit main(). */
if (no_cleanup)
_exit(0);
else
exit(0);
} else {
/* We're a thread */
exit_thread(0);
}
}
void PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
dprintf(("PyThread_exit_prog(%d) called\n", status));
/* No need to do anything, the threads get torn down if main()exits. */
if (no_cleanup)
_exit(status);
else
exit(status);
/* No need to do anything, the threads get torn down if main()exits. */
if (no_cleanup)
_exit(status);
else
exit(status);
}
void PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
#endif /* NO_EXIT_PROG */
/*
@ -194,107 +194,107 @@ static atomic_t lock_count = 0;
PyThread_type_lock PyThread_allocate_lock(void)
{
#ifdef FASTLOCK
fastmutex_t *lock;
fastmutex_t *lock;
#else
sem_id sema;
sem_id sema;
#endif
char name[OS_NAME_LENGTH];
atomic_t this_lock;
char name[OS_NAME_LENGTH];
atomic_t this_lock;
dprintf(("PyThread_allocate_lock called\n"));
dprintf(("PyThread_allocate_lock called\n"));
#ifdef FASTLOCK
lock = (fastmutex_t *) malloc(sizeof(fastmutex_t));
if (lock == NULL) {
dprintf(("PyThread_allocate_lock failed: out of memory\n"));
return (PyThread_type_lock) NULL;
}
lock = (fastmutex_t *) malloc(sizeof(fastmutex_t));
if (lock == NULL) {
dprintf(("PyThread_allocate_lock failed: out of memory\n"));
return (PyThread_type_lock) NULL;
}
#endif
this_lock = atomic_add(&lock_count, 1);
PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock);
this_lock = atomic_add(&lock_count, 1);
PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock);
#ifdef FASTLOCK
if (fastmutex_create(name, lock) < 0) {
dprintf(("PyThread_allocate_lock failed: %s\n",
strerror(errno)));
free(lock);
lock = NULL;
}
dprintf(("PyThread_allocate_lock()-> %p\n", lock));
return (PyThread_type_lock) lock;
if (fastmutex_create(name, lock) < 0) {
dprintf(("PyThread_allocate_lock failed: %s\n",
strerror(errno)));
free(lock);
lock = NULL;
}
dprintf(("PyThread_allocate_lock()-> %p\n", lock));
return (PyThread_type_lock) lock;
#else
sema = create_semaphore(name, 1, 0);
if (sema < 0) {
dprintf(("PyThread_allocate_lock failed: %s\n",
strerror(errno)));
sema = 0;
}
dprintf(("PyThread_allocate_lock()-> %p\n", sema));
return (PyThread_type_lock) sema;
sema = create_semaphore(name, 1, 0);
if (sema < 0) {
dprintf(("PyThread_allocate_lock failed: %s\n",
strerror(errno)));
sema = 0;
}
dprintf(("PyThread_allocate_lock()-> %p\n", sema));
return (PyThread_type_lock) sema;
#endif
}
void PyThread_free_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_free_lock(%p) called\n", lock));
dprintf(("PyThread_free_lock(%p) called\n", lock));
#ifdef FASTLOCK
if (fastmutex_destroy((fastmutex_t *) lock) < 0) {
dprintf(("PyThread_free_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
free(lock);
if (fastmutex_destroy((fastmutex_t *) lock) < 0) {
dprintf(("PyThread_free_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
free(lock);
#else
if (delete_semaphore((sem_id) lock) < 0) {
dprintf(("PyThread_free_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
if (delete_semaphore((sem_id) lock) < 0) {
dprintf(("PyThread_free_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
#endif
}
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int retval;
int retval;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock,
waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock,
waitflag));
#ifdef FASTLOCK
if (waitflag)
retval = fastmutex_lock((fastmutex_t *) lock);
else
retval = fastmutex_timedlock((fastmutex_t *) lock, 0);
if (waitflag)
retval = fastmutex_lock((fastmutex_t *) lock);
else
retval = fastmutex_timedlock((fastmutex_t *) lock, 0);
#else
if (waitflag)
retval = lock_semaphore((sem_id) lock);
else
retval = lock_semaphore_x((sem_id) lock, 1, 0, 0);
if (waitflag)
retval = lock_semaphore((sem_id) lock);
else
retval = lock_semaphore_x((sem_id) lock, 1, 0, 0);
#endif
if (retval < 0) {
dprintf(("PyThread_acquire_lock(%p, %d) failed: %s\n",
lock, waitflag, strerror(errno)));
}
dprintf(("PyThread_acquire_lock(%p, %d)-> %d\n", lock, waitflag,
retval));
return retval < 0 ? 0 : 1;
if (retval < 0) {
dprintf(("PyThread_acquire_lock(%p, %d) failed: %s\n",
lock, waitflag, strerror(errno)));
}
dprintf(("PyThread_acquire_lock(%p, %d)-> %d\n", lock, waitflag,
retval));
return retval < 0 ? 0 : 1;
}
void PyThread_release_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_release_lock(%p) called\n", lock));
dprintf(("PyThread_release_lock(%p) called\n", lock));
#ifdef FASTLOCK
if (fastmutex_unlock((fastmutex_t *) lock) < 0) {
dprintf(("PyThread_release_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
if (fastmutex_unlock((fastmutex_t *) lock) < 0) {
dprintf(("PyThread_release_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
#else
if (unlock_semaphore((sem_id) lock) < 0) {
dprintf(("PyThread_release_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
if (unlock_semaphore((sem_id) lock) < 0) {
dprintf(("PyThread_release_lock(%p) failed: %s\n", lock,
strerror(errno)));
}
#endif
}

View file

@ -7,8 +7,8 @@
* in the Be Developer's Newsletter, Issue #26 (http://www.be.com/).
*/
typedef struct benaphore {
sem_id _sem;
int32 _atom;
sem_id _sem;
int32 _atom;
} benaphore_t;
static status_t benaphore_create( const char *name, benaphore_t *ben );
@ -19,79 +19,79 @@ static status_t benaphore_unlock( benaphore_t *ben );
static status_t benaphore_create( const char *name, benaphore_t *ben )
{
if( ben != NULL ) {
ben->_atom = 0;
ben->_sem = create_sem( 0, name );
if( ben->_sem < B_NO_ERROR ) {
return B_BAD_SEM_ID;
}
} else {
return EFAULT;
}
return EOK;
if( ben != NULL ) {
ben->_atom = 0;
ben->_sem = create_sem( 0, name );
if( ben->_sem < B_NO_ERROR ) {
return B_BAD_SEM_ID;
}
} else {
return EFAULT;
}
return EOK;
}
static status_t benaphore_destroy( benaphore_t *ben )
{
if( ben->_sem >= B_NO_ERROR ) {
status_t retval = benaphore_timedlock( ben, 0 );
if( retval == EOK || retval == EWOULDBLOCK ) {
status_t del_retval = delete_sem( ben->_sem );
return del_retval;
}
}
if( ben->_sem >= B_NO_ERROR ) {
status_t retval = benaphore_timedlock( ben, 0 );
return B_BAD_SEM_ID;
if( retval == EOK || retval == EWOULDBLOCK ) {
status_t del_retval = delete_sem( ben->_sem );
return del_retval;
}
}
return B_BAD_SEM_ID;
}
static status_t benaphore_lock( benaphore_t *ben )
{
int32 prev = atomic_add( &(ben->_atom), 1 );
if( prev > 0 ) {
return acquire_sem( ben->_sem );
}
return EOK;
int32 prev = atomic_add( &(ben->_atom), 1 );
if( prev > 0 ) {
return acquire_sem( ben->_sem );
}
return EOK;
}
static status_t benaphore_timedlock( benaphore_t *ben, bigtime_t micros )
{
int32 prev = atomic_add( &(ben->_atom), 1 );
if( prev > 0 ) {
status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros );
switch( retval ) {
case B_WOULD_BLOCK: /* Fall through... */
case B_TIMED_OUT:
return EWOULDBLOCK;
break;
case B_OK:
return EOK;
break;
default:
return retval;
break;
}
}
return EOK;
int32 prev = atomic_add( &(ben->_atom), 1 );
if( prev > 0 ) {
status_t retval = acquire_sem_etc( ben->_sem, 1, B_TIMEOUT, micros );
switch( retval ) {
case B_WOULD_BLOCK: /* Fall through... */
case B_TIMED_OUT:
return EWOULDBLOCK;
break;
case B_OK:
return EOK;
break;
default:
return retval;
break;
}
}
return EOK;
}
static status_t benaphore_unlock( benaphore_t *ben )
{
int32 prev = atomic_add( &(ben->_atom), -1 );
if( prev > 1 ) {
return release_sem( ben->_sem );
}
return EOK;
int32 prev = atomic_add( &(ben->_atom), -1 );
if( prev > 1 ) {
return release_sem( ben->_sem );
}
return EOK;
}
/* ----------------------------------------------------------------------
@ -99,8 +99,8 @@ static status_t benaphore_unlock( benaphore_t *ben )
*/
static void PyThread__init_thread( void )
{
/* Do nothing. */
return;
/* Do nothing. */
return;
}
/* ----------------------------------------------------------------------
@ -114,90 +114,90 @@ static int32 thread_count = 0;
long PyThread_start_new_thread( void (*func)(void *), void *arg )
{
status_t success = 0;
thread_id tid;
char name[B_OS_NAME_LENGTH];
int32 this_thread;
status_t success = 0;
thread_id tid;
char name[B_OS_NAME_LENGTH];
int32 this_thread;
dprintf(("PyThread_start_new_thread called\n"));
dprintf(("PyThread_start_new_thread called\n"));
/* We are so very thread-safe... */
this_thread = atomic_add( &thread_count, 1 );
PyOS_snprintf(name, sizeof(name),
"python thread (%d)", this_thread );
/* We are so very thread-safe... */
this_thread = atomic_add( &thread_count, 1 );
PyOS_snprintf(name, sizeof(name),
"python thread (%d)", this_thread );
tid = spawn_thread( (thread_func)func, name,
B_NORMAL_PRIORITY, arg );
if( tid > B_NO_ERROR ) {
success = resume_thread( tid );
}
tid = spawn_thread( (thread_func)func, name,
B_NORMAL_PRIORITY, arg );
if( tid > B_NO_ERROR ) {
success = resume_thread( tid );
}
return ( success == B_NO_ERROR ? tid : -1 );
return ( success == B_NO_ERROR ? tid : -1 );
}
long PyThread_get_thread_ident( void )
{
/* Presumed to return the current thread's ID... */
thread_id tid;
tid = find_thread( NULL );
return ( tid != B_NAME_NOT_FOUND ? tid : -1 );
/* Presumed to return the current thread's ID... */
thread_id tid;
tid = find_thread( NULL );
return ( tid != B_NAME_NOT_FOUND ? tid : -1 );
}
static void do_PyThread_exit_thread( int no_cleanup )
{
int32 threads;
int32 threads;
dprintf(("PyThread_exit_thread called\n"));
dprintf(("PyThread_exit_thread called\n"));
/* Thread-safe way to read a variable without a mutex: */
threads = atomic_add( &thread_count, 0 );
/* Thread-safe way to read a variable without a mutex: */
threads = atomic_add( &thread_count, 0 );
if( threads == 0 ) {
/* No threads around, so exit main(). */
if( no_cleanup ) {
_exit(0);
} else {
exit(0);
}
} else {
/* Oh, we're a thread, let's try to exit gracefully... */
exit_thread( B_NO_ERROR );
}
if( threads == 0 ) {
/* No threads around, so exit main(). */
if( no_cleanup ) {
_exit(0);
} else {
exit(0);
}
} else {
/* Oh, we're a thread, let's try to exit gracefully... */
exit_thread( B_NO_ERROR );
}
}
void PyThread_exit_thread( void )
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void PyThread__exit_thread( void )
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog( int status, int no_cleanup )
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
dprintf(("PyThread_exit_prog(%d) called\n", status));
/* No need to do anything, the threads get torn down if main() exits. */
/* No need to do anything, the threads get torn down if main() exits. */
if (no_cleanup) {
_exit(status);
} else {
exit(status);
}
if (no_cleanup) {
_exit(status);
} else {
exit(status);
}
}
void PyThread_exit_prog( int status )
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void PyThread__exit_prog( int status )
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -209,79 +209,79 @@ static int32 lock_count = 0;
PyThread_type_lock PyThread_allocate_lock( void )
{
benaphore_t *lock;
status_t retval;
char name[B_OS_NAME_LENGTH];
int32 this_lock;
dprintf(("PyThread_allocate_lock called\n"));
benaphore_t *lock;
status_t retval;
char name[B_OS_NAME_LENGTH];
int32 this_lock;
lock = (benaphore_t *)malloc( sizeof( benaphore_t ) );
if( lock == NULL ) {
/* TODO: that's bad, raise MemoryError */
return (PyThread_type_lock)NULL;
}
dprintf(("PyThread_allocate_lock called\n"));
this_lock = atomic_add( &lock_count, 1 );
PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock);
lock = (benaphore_t *)malloc( sizeof( benaphore_t ) );
if( lock == NULL ) {
/* TODO: that's bad, raise MemoryError */
return (PyThread_type_lock)NULL;
}
retval = benaphore_create( name, lock );
if( retval != EOK ) {
/* TODO: that's bad, raise an exception */
return (PyThread_type_lock)NULL;
}
this_lock = atomic_add( &lock_count, 1 );
PyOS_snprintf(name, sizeof(name), "python lock (%d)", this_lock);
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
retval = benaphore_create( name, lock );
if( retval != EOK ) {
/* TODO: that's bad, raise an exception */
return (PyThread_type_lock)NULL;
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void PyThread_free_lock( PyThread_type_lock lock )
{
status_t retval;
status_t retval;
dprintf(("PyThread_free_lock(%p) called\n", lock));
retval = benaphore_destroy( (benaphore_t *)lock );
if( retval != EOK ) {
/* TODO: that's bad, raise an exception */
return;
}
dprintf(("PyThread_free_lock(%p) called\n", lock));
retval = benaphore_destroy( (benaphore_t *)lock );
if( retval != EOK ) {
/* TODO: that's bad, raise an exception */
return;
}
}
int PyThread_acquire_lock( PyThread_type_lock lock, int waitflag )
{
int success;
status_t retval;
int success;
status_t retval;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
if( waitflag ) {
retval = benaphore_lock( (benaphore_t *)lock );
} else {
retval = benaphore_timedlock( (benaphore_t *)lock, 0 );
}
if( retval == EOK ) {
success = 1;
} else {
success = 0;
/* TODO: that's bad, raise an exception */
}
if( waitflag ) {
retval = benaphore_lock( (benaphore_t *)lock );
} else {
retval = benaphore_timedlock( (benaphore_t *)lock, 0 );
}
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
if( retval == EOK ) {
success = 1;
} else {
success = 0;
/* TODO: that's bad, raise an exception */
}
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void PyThread_release_lock( PyThread_type_lock lock )
{
status_t retval;
dprintf(("PyThread_release_lock(%p) called\n", lock));
retval = benaphore_unlock( (benaphore_t *)lock );
if( retval != EOK ) {
/* TODO: that's bad, raise an exception */
return;
}
status_t retval;
dprintf(("PyThread_release_lock(%p) called\n", lock));
retval = benaphore_unlock( (benaphore_t *)lock );
if( retval != EOK ) {
/* TODO: that's bad, raise an exception */
return;
}
}

View file

@ -14,12 +14,12 @@ static void
PyThread__init_thread(void)
{
#ifndef HURD_C_THREADS
/* Roland McGrath said this should not be used since this is
done while linking to threads */
cthread_init();
/* Roland McGrath said this should not be used since this is
done while linking to threads */
cthread_init();
#else
/* do nothing */
;
;
#endif
}
@ -29,77 +29,77 @@ PyThread__init_thread(void)
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
/* looks like solaris detaches the thread to never rejoin
* so well do it here
*/
cthread_detach(cthread_fork((cthread_fn_t) func, arg));
return success < 0 ? -1 : 0;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
/* looks like solaris detaches the thread to never rejoin
* so well do it here
*/
cthread_detach(cthread_fork((cthread_fn_t) func, arg));
return success < 0 ? -1 : 0;
}
long
PyThread_get_thread_ident(void)
{
if (!initialized)
PyThread_init_thread();
return (long) cthread_self();
if (!initialized)
PyThread_init_thread();
return (long) cthread_self();
}
static void
do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
cthread_exit(0);
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
cthread_exit(0);
}
void
PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void
PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static
void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
if (no_cleanup)
_exit(status);
else
exit(status);
}
void
PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void
PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -109,48 +109,48 @@ PyThread__exit_prog(int status)
PyThread_type_lock
PyThread_allocate_lock(void)
{
mutex_t lock;
mutex_t lock;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock = mutex_alloc();
if (mutex_init(lock)) {
perror("mutex_init");
free((void *) lock);
lock = 0;
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
lock = mutex_alloc();
if (mutex_init(lock)) {
perror("mutex_init");
free((void *) lock);
lock = 0;
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void
PyThread_free_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_free_lock(%p) called\n", lock));
mutex_free(lock);
dprintf(("PyThread_free_lock(%p) called\n", lock));
mutex_free(lock);
}
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success = FALSE;
int success = FALSE;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
if (waitflag) { /* blocking */
mutex_lock((mutex_t)lock);
success = TRUE;
} else { /* non blocking */
success = mutex_try_lock((mutex_t)lock);
}
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
if (waitflag) { /* blocking */
mutex_lock((mutex_t)lock);
success = TRUE;
} else { /* non blocking */
success = mutex_try_lock((mutex_t)lock);
}
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void
PyThread_release_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_release_lock(%p) called\n", lock));
mutex_unlock((mutex_t )lock);
dprintf(("PyThread_release_lock(%p) called\n", lock));
mutex_unlock((mutex_t )lock);
}

View file

@ -13,67 +13,67 @@ PyThread__init_thread(void)
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
return success < 0 ? -1 : 0;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
return success < 0 ? -1 : 0;
}
long
PyThread_get_thread_ident(void)
{
if (!initialized)
PyThread_init_thread();
if (!initialized)
PyThread_init_thread();
}
static
void do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
}
void
PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void
PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static
void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
}
void
PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void
PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -84,32 +84,32 @@ PyThread_type_lock
PyThread_allocate_lock(void)
{
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void
PyThread_free_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_free_lock(%p) called\n", lock));
dprintf(("PyThread_free_lock(%p) called\n", lock));
}
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
int success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void
PyThread_release_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_release_lock(%p) called\n", lock));
dprintf(("PyThread_release_lock(%p) called\n", lock));
}

View file

@ -3,13 +3,13 @@
#include <lwp/lwp.h>
#include <lwp/stackdep.h>
#define STACKSIZE 1000 /* stacksize for a thread */
#define NSTACKS 2 /* # stacks to be put in cache initially */
#define STACKSIZE 1000 /* stacksize for a thread */
#define NSTACKS 2 /* # stacks to be put in cache initially */
struct lock {
int lock_locked;
cv_t lock_condvar;
mon_t lock_monitor;
int lock_locked;
cv_t lock_condvar;
mon_t lock_monitor;
};
@ -18,7 +18,7 @@ struct lock {
*/
static void PyThread__init_thread(void)
{
lwp_setstkcache(STACKSIZE, NSTACKS);
lwp_setstkcache(STACKSIZE, NSTACKS);
}
/*
@ -28,66 +28,66 @@ static void PyThread__init_thread(void)
long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
thread_t tid;
int success;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
return success < 0 ? -1 : 0;
thread_t tid;
int success;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
return success < 0 ? -1 : 0;
}
long PyThread_get_thread_ident(void)
{
thread_t tid;
if (!initialized)
PyThread_init_thread();
if (lwp_self(&tid) < 0)
return -1;
return tid.thread_id;
thread_t tid;
if (!initialized)
PyThread_init_thread();
if (lwp_self(&tid) < 0)
return -1;
return tid.thread_id;
}
static void do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
lwp_destroy(SELF);
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
lwp_destroy(SELF);
}
void PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
pod_exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
pod_exit(status);
}
void PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -96,54 +96,54 @@ void PyThread__exit_prog(int status)
*/
PyThread_type_lock PyThread_allocate_lock(void)
{
struct lock *lock;
extern char *malloc(size_t);
struct lock *lock;
extern char *malloc(size_t);
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock = (struct lock *) malloc(sizeof(struct lock));
lock->lock_locked = 0;
(void) mon_create(&lock->lock_monitor);
(void) cv_create(&lock->lock_condvar, lock->lock_monitor);
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
lock = (struct lock *) malloc(sizeof(struct lock));
lock->lock_locked = 0;
(void) mon_create(&lock->lock_monitor);
(void) cv_create(&lock->lock_condvar, lock->lock_monitor);
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void PyThread_free_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_free_lock(%p) called\n", lock));
mon_destroy(((struct lock *) lock)->lock_monitor);
free((char *) lock);
dprintf(("PyThread_free_lock(%p) called\n", lock));
mon_destroy(((struct lock *) lock)->lock_monitor);
free((char *) lock);
}
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
int success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
success = 0;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
success = 0;
(void) mon_enter(((struct lock *) lock)->lock_monitor);
if (waitflag)
while (((struct lock *) lock)->lock_locked)
cv_wait(((struct lock *) lock)->lock_condvar);
if (!((struct lock *) lock)->lock_locked) {
success = 1;
((struct lock *) lock)->lock_locked = 1;
}
cv_broadcast(((struct lock *) lock)->lock_condvar);
mon_exit(((struct lock *) lock)->lock_monitor);
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
(void) mon_enter(((struct lock *) lock)->lock_monitor);
if (waitflag)
while (((struct lock *) lock)->lock_locked)
cv_wait(((struct lock *) lock)->lock_condvar);
if (!((struct lock *) lock)->lock_locked) {
success = 1;
((struct lock *) lock)->lock_locked = 1;
}
cv_broadcast(((struct lock *) lock)->lock_condvar);
mon_exit(((struct lock *) lock)->lock_monitor);
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void PyThread_release_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_release_lock(%p) called\n", lock));
(void) mon_enter(((struct lock *) lock)->lock_monitor);
((struct lock *) lock)->lock_locked = 0;
cv_broadcast(((struct lock *) lock)->lock_condvar);
mon_exit(((struct lock *) lock)->lock_monitor);
dprintf(("PyThread_release_lock(%p) called\n", lock));
(void) mon_enter(((struct lock *) lock)->lock_monitor);
((struct lock *) lock)->lock_locked = 0;
cv_broadcast(((struct lock *) lock)->lock_condvar);
mon_exit(((struct lock *) lock)->lock_monitor);
}

View file

@ -10,81 +10,81 @@
#endif
typedef struct NRMUTEX {
LONG owned ;
DWORD thread_id ;
HANDLE hevent ;
LONG owned ;
DWORD thread_id ;
HANDLE hevent ;
} NRMUTEX, *PNRMUTEX ;
BOOL
InitializeNonRecursiveMutex(PNRMUTEX mutex)
{
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
mutex->thread_id = 0 ;
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
mutex->owned = -1 ; /* No threads have entered NonRecursiveMutex */
mutex->thread_id = 0 ;
mutex->hevent = CreateEvent(NULL, FALSE, FALSE, NULL) ;
return mutex->hevent != NULL ; /* TRUE if the mutex is created */
}
VOID
DeleteNonRecursiveMutex(PNRMUTEX mutex)
{
/* No in-use check */
CloseHandle(mutex->hevent) ;
mutex->hevent = NULL ; /* Just in case */
/* No in-use check */
CloseHandle(mutex->hevent) ;
mutex->hevent = NULL ; /* Just in case */
}
DWORD
EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait)
{
/* Assume that the thread waits successfully */
DWORD ret ;
/* Assume that the thread waits successfully */
DWORD ret ;
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
if (!wait)
{
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
return WAIT_TIMEOUT ;
ret = WAIT_OBJECT_0 ;
}
else
ret = InterlockedIncrement(&mutex->owned) ?
/* Some thread owns the mutex, let's wait... */
WaitForSingleObject(mutex->hevent, INFINITE) : WAIT_OBJECT_0 ;
/* InterlockedIncrement(&mutex->owned) == 0 means that no thread currently owns the mutex */
if (!wait)
{
if (InterlockedCompareExchange(&mutex->owned, 0, -1) != -1)
return WAIT_TIMEOUT ;
ret = WAIT_OBJECT_0 ;
}
else
ret = InterlockedIncrement(&mutex->owned) ?
/* Some thread owns the mutex, let's wait... */
WaitForSingleObject(mutex->hevent, INFINITE) : WAIT_OBJECT_0 ;
mutex->thread_id = GetCurrentThreadId() ; /* We own it */
return ret ;
mutex->thread_id = GetCurrentThreadId() ; /* We own it */
return ret ;
}
BOOL
LeaveNonRecursiveMutex(PNRMUTEX mutex)
{
/* We don't own the mutex */
mutex->thread_id = 0 ;
return
InterlockedDecrement(&mutex->owned) < 0 ||
SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */
/* We don't own the mutex */
mutex->thread_id = 0 ;
return
InterlockedDecrement(&mutex->owned) < 0 ||
SetEvent(mutex->hevent) ; /* Other threads are waiting, wake one on them up */
}
PNRMUTEX
AllocNonRecursiveMutex(void)
{
PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
if (mutex && !InitializeNonRecursiveMutex(mutex))
{
free(mutex) ;
mutex = NULL ;
}
return mutex ;
PNRMUTEX mutex = (PNRMUTEX)malloc(sizeof(NRMUTEX)) ;
if (mutex && !InitializeNonRecursiveMutex(mutex))
{
free(mutex) ;
mutex = NULL ;
}
return mutex ;
}
void
FreeNonRecursiveMutex(PNRMUTEX mutex)
{
if (mutex)
{
DeleteNonRecursiveMutex(mutex) ;
free(mutex) ;
}
if (mutex)
{
DeleteNonRecursiveMutex(mutex) ;
free(mutex) ;
}
}
long PyThread_get_thread_ident(void);
@ -102,65 +102,65 @@ PyThread__init_thread(void)
*/
typedef struct {
void (*func)(void*);
void *arg;
long id;
HANDLE done;
void (*func)(void*);
void *arg;
long id;
HANDLE done;
} callobj;
static int
bootstrap(void *call)
{
callobj *obj = (callobj*)call;
/* copy callobj since other thread might free it before we're done */
void (*func)(void*) = obj->func;
void *arg = obj->arg;
callobj *obj = (callobj*)call;
/* copy callobj since other thread might free it before we're done */
void (*func)(void*) = obj->func;
void *arg = obj->arg;
obj->id = PyThread_get_thread_ident();
ReleaseSemaphore(obj->done, 1, NULL);
func(arg);
return 0;
obj->id = PyThread_get_thread_ident();
ReleaseSemaphore(obj->done, 1, NULL);
func(arg);
return 0;
}
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
Py_uintptr_t rv;
callobj obj;
Py_uintptr_t rv;
callobj obj;
dprintf(("%ld: PyThread_start_new_thread called\n",
PyThread_get_thread_ident()));
if (!initialized)
PyThread_init_thread();
dprintf(("%ld: PyThread_start_new_thread called\n",
PyThread_get_thread_ident()));
if (!initialized)
PyThread_init_thread();
obj.id = -1; /* guilty until proved innocent */
obj.func = func;
obj.arg = arg;
obj.done = CreateSemaphore(NULL, 0, 1, NULL);
if (obj.done == NULL)
return -1;
obj.id = -1; /* guilty until proved innocent */
obj.func = func;
obj.arg = arg;
obj.done = CreateSemaphore(NULL, 0, 1, NULL);
if (obj.done == NULL)
return -1;
rv = _beginthread(bootstrap,
Py_SAFE_DOWNCAST(_pythread_stacksize,
Py_ssize_t, int),
&obj);
if (rv == (Py_uintptr_t)-1) {
/* I've seen errno == EAGAIN here, which means "there are
* too many threads".
*/
dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n",
PyThread_get_thread_ident(), (void*)rv, errno));
obj.id = -1;
}
else {
dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
PyThread_get_thread_ident(), (void*)rv));
/* wait for thread to initialize, so we can get its id */
WaitForSingleObject(obj.done, INFINITE);
assert(obj.id != -1);
}
CloseHandle((HANDLE)obj.done);
return obj.id;
rv = _beginthread(bootstrap,
Py_SAFE_DOWNCAST(_pythread_stacksize,
Py_ssize_t, int),
&obj);
if (rv == (Py_uintptr_t)-1) {
/* I've seen errno == EAGAIN here, which means "there are
* too many threads".
*/
dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n",
PyThread_get_thread_ident(), (void*)rv, errno));
obj.id = -1;
}
else {
dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n",
PyThread_get_thread_ident(), (void*)rv));
/* wait for thread to initialize, so we can get its id */
WaitForSingleObject(obj.done, INFINITE);
assert(obj.id != -1);
}
CloseHandle((HANDLE)obj.done);
return obj.id;
}
/*
@ -170,58 +170,58 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
long
PyThread_get_thread_ident(void)
{
if (!initialized)
PyThread_init_thread();
if (!initialized)
PyThread_init_thread();
return GetCurrentThreadId();
return GetCurrentThreadId();
}
static void
do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
_endthread();
dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
_endthread();
}
void
PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void
PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void
do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
}
void
PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void
PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -233,25 +233,25 @@ PyThread__exit_prog(int status)
PyThread_type_lock
PyThread_allocate_lock(void)
{
PNRMUTEX aLock;
PNRMUTEX aLock;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
aLock = AllocNonRecursiveMutex() ;
aLock = AllocNonRecursiveMutex() ;
dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
return (PyThread_type_lock) aLock;
return (PyThread_type_lock) aLock;
}
void
PyThread_free_lock(PyThread_type_lock aLock)
{
dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
FreeNonRecursiveMutex(aLock) ;
FreeNonRecursiveMutex(aLock) ;
}
/*
@ -263,29 +263,29 @@ PyThread_free_lock(PyThread_type_lock aLock)
int
PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
{
int success ;
int success ;
dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag));
dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag));
success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ;
success = aLock && EnterNonRecursiveMutex((PNRMUTEX) aLock, (waitflag ? INFINITE : 0)) == WAIT_OBJECT_0 ;
dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
return success;
return success;
}
void
PyThread_release_lock(PyThread_type_lock aLock)
{
dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
if (!(aLock && LeaveNonRecursiveMutex((PNRMUTEX) aLock)))
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %ld\n", PyThread_get_thread_ident(), aLock, GetLastError()));
}
/* minimum/maximum thread stack sizes supported */
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
#define THREAD_MAX_STACKSIZE 0x10000000 /* 256MB */
/* set the thread stack size.
* Return 0 if size is valid, -1 otherwise.
@ -293,19 +293,19 @@ PyThread_release_lock(PyThread_type_lock aLock)
static int
_pythread_nt_set_stacksize(size_t size)
{
/* set to default */
if (size == 0) {
_pythread_stacksize = 0;
return 0;
}
/* set to default */
if (size == 0) {
_pythread_stacksize = 0;
return 0;
}
/* valid range? */
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
_pythread_stacksize = size;
return 0;
}
/* valid range? */
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
_pythread_stacksize = size;
return 0;
}
return -1;
return -1;
}
#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)
#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)

View file

@ -16,10 +16,10 @@ long PyThread_get_thread_ident(void);
/* default thread stack size of 64kB */
#if !defined(THREAD_STACK_SIZE)
#define THREAD_STACK_SIZE 0x10000
#define THREAD_STACK_SIZE 0x10000
#endif
#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
#define OS2_STACKSIZE(x) (x ? x : THREAD_STACK_SIZE)
/*
* Initialization of the C package, should not be needed.
@ -35,153 +35,153 @@ PyThread__init_thread(void)
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
int thread_id;
int thread_id;
thread_id = _beginthread(func,
NULL,
OS2_STACKSIZE(_pythread_stacksize),
arg);
thread_id = _beginthread(func,
NULL,
OS2_STACKSIZE(_pythread_stacksize),
arg);
if (thread_id == -1) {
dprintf(("_beginthread failed. return %ld\n", errno));
}
if (thread_id == -1) {
dprintf(("_beginthread failed. return %ld\n", errno));
}
return thread_id;
return thread_id;
}
long
PyThread_get_thread_ident(void)
{
#if !defined(PYCC_GCC)
PPIB pib;
PTIB tib;
PPIB pib;
PTIB tib;
#endif
if (!initialized)
PyThread_init_thread();
if (!initialized)
PyThread_init_thread();
#if defined(PYCC_GCC)
return _gettid();
return _gettid();
#else
DosGetInfoBlocks(&tib, &pib);
return tib->tib_ptib2->tib2_ultid;
DosGetInfoBlocks(&tib, &pib);
return tib->tib_ptib2->tib2_ultid;
#endif
}
static void
do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("%ld: PyThread_exit_thread called\n",
PyThread_get_thread_ident()));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
_endthread();
dprintf(("%ld: PyThread_exit_thread called\n",
PyThread_get_thread_ident()));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
_endthread();
}
void
void
PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void
void
PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void
static void
do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
}
void
void
PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void
void
PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
/*
* Lock support. This is implemented with an event semaphore and critical
* sections to make it behave more like a posix mutex than its OS/2
* sections to make it behave more like a posix mutex than its OS/2
* counterparts.
*/
typedef struct os2_lock_t {
int is_set;
HEV changed;
int is_set;
HEV changed;
} *type_os2_lock;
PyThread_type_lock
PyThread_type_lock
PyThread_allocate_lock(void)
{
#if defined(PYCC_GCC)
_fmutex *sem = malloc(sizeof(_fmutex));
if (!initialized)
PyThread_init_thread();
dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
PyThread_get_thread_ident(),
(long)sem));
if (_fmutex_create(sem, 0)) {
free(sem);
sem = NULL;
}
return (PyThread_type_lock)sem;
_fmutex *sem = malloc(sizeof(_fmutex));
if (!initialized)
PyThread_init_thread();
dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",
PyThread_get_thread_ident(),
(long)sem));
if (_fmutex_create(sem, 0)) {
free(sem);
sem = NULL;
}
return (PyThread_type_lock)sem;
#else
APIRET rc;
type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
APIRET rc;
type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t));
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock->is_set = 0;
lock->is_set = 0;
DosCreateEventSem(NULL, &lock->changed, 0, 0);
DosCreateEventSem(NULL, &lock->changed, 0, 0);
dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
PyThread_get_thread_ident(),
lock->changed));
dprintf(("%ld: PyThread_allocate_lock() -> %p\n",
PyThread_get_thread_ident(),
lock->changed));
return (PyThread_type_lock)lock;
return (PyThread_type_lock)lock;
#endif
}
void
void
PyThread_free_lock(PyThread_type_lock aLock)
{
#if !defined(PYCC_GCC)
type_os2_lock lock = (type_os2_lock)aLock;
type_os2_lock lock = (type_os2_lock)aLock;
#endif
dprintf(("%ld: PyThread_free_lock(%p) called\n",
PyThread_get_thread_ident(),aLock));
dprintf(("%ld: PyThread_free_lock(%p) called\n",
PyThread_get_thread_ident(),aLock));
#if defined(PYCC_GCC)
if (aLock) {
_fmutex_close((_fmutex *)aLock);
free((_fmutex *)aLock);
}
if (aLock) {
_fmutex_close((_fmutex *)aLock);
free((_fmutex *)aLock);
}
#else
DosCloseEventSem(lock->changed);
free(aLock);
DosCloseEventSem(lock->changed);
free(aLock);
#endif
}
@ -190,98 +190,98 @@ PyThread_free_lock(PyThread_type_lock aLock)
*
* and 0 if the lock was not acquired.
*/
int
int
PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
{
#if !defined(PYCC_GCC)
int done = 0;
ULONG count;
PID pid = 0;
TID tid = 0;
type_os2_lock lock = (type_os2_lock)aLock;
int done = 0;
ULONG count;
PID pid = 0;
TID tid = 0;
type_os2_lock lock = (type_os2_lock)aLock;
#endif
dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
PyThread_get_thread_ident(),
aLock,
waitflag));
dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",
PyThread_get_thread_ident(),
aLock,
waitflag));
#if defined(PYCC_GCC)
/* always successful if the lock doesn't exist */
if (aLock &&
_fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
return 0;
/* always successful if the lock doesn't exist */
if (aLock &&
_fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))
return 0;
#else
while (!done) {
/* if the lock is currently set, we have to wait for
* the state to change
*/
if (lock->is_set) {
if (!waitflag)
return 0;
DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
}
while (!done) {
/* if the lock is currently set, we have to wait for
* the state to change
*/
if (lock->is_set) {
if (!waitflag)
return 0;
DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);
}
/* enter a critical section and try to get the semaphore. If
* it is still locked, we will try again.
*/
if (DosEnterCritSec())
return 0;
/* enter a critical section and try to get the semaphore. If
* it is still locked, we will try again.
*/
if (DosEnterCritSec())
return 0;
if (!lock->is_set) {
lock->is_set = 1;
DosResetEventSem(lock->changed, &count);
done = 1;
}
if (!lock->is_set) {
lock->is_set = 1;
DosResetEventSem(lock->changed, &count);
done = 1;
}
DosExitCritSec();
}
DosExitCritSec();
}
#endif
return 1;
return 1;
}
void
PyThread_release_lock(PyThread_type_lock aLock)
{
#if !defined(PYCC_GCC)
type_os2_lock lock = (type_os2_lock)aLock;
type_os2_lock lock = (type_os2_lock)aLock;
#endif
dprintf(("%ld: PyThread_release_lock(%p) called\n",
PyThread_get_thread_ident(),
aLock));
dprintf(("%ld: PyThread_release_lock(%p) called\n",
PyThread_get_thread_ident(),
aLock));
#if defined(PYCC_GCC)
if (aLock)
_fmutex_release((_fmutex *)aLock);
if (aLock)
_fmutex_release((_fmutex *)aLock);
#else
if (!lock->is_set) {
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
PyThread_get_thread_ident(),
aLock,
GetLastError()));
return;
}
if (!lock->is_set) {
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
PyThread_get_thread_ident(),
aLock,
GetLastError()));
return;
}
if (DosEnterCritSec()) {
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
PyThread_get_thread_ident(),
aLock,
GetLastError()));
return;
}
if (DosEnterCritSec()) {
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",
PyThread_get_thread_ident(),
aLock,
GetLastError()));
return;
}
lock->is_set = 0;
DosPostEventSem(lock->changed);
lock->is_set = 0;
DosPostEventSem(lock->changed);
DosExitCritSec();
DosExitCritSec();
#endif
}
/* minimum/maximum thread stack sizes supported */
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */
#define THREAD_MIN_STACKSIZE 0x8000 /* 32kB */
#define THREAD_MAX_STACKSIZE 0x2000000 /* 32MB */
/* set the thread stack size.
* Return 0 if size is valid, -1 otherwise.
@ -289,19 +289,19 @@ PyThread_release_lock(PyThread_type_lock aLock)
static int
_pythread_os2_set_stacksize(size_t size)
{
/* set to default */
if (size == 0) {
_pythread_stacksize = 0;
return 0;
}
/* set to default */
if (size == 0) {
_pythread_stacksize = 0;
return 0;
}
/* valid range? */
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
_pythread_stacksize = size;
return 0;
}
/* valid range? */
if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {
_pythread_stacksize = size;
return 0;
}
return -1;
return -1;
}
#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)
#define THREAD_SET_STACKSIZE(x) _pythread_os2_set_stacksize(x)

View file

@ -3,7 +3,7 @@
http://www.gnu.org/software/pth
2000-05-03 Andy Dustman <andy@dustman.net>
Adapted from Posix threads interface
Adapted from Posix threads interface
12 May 1997 -- david arnold <davida@pobox.com>
*/
@ -22,10 +22,10 @@
*/
typedef struct {
char locked; /* 0=unlocked, 1=locked */
/* a <cond, mutex> pair to handle an acquire of a locked lock */
pth_cond_t lock_released;
pth_mutex_t mut;
char locked; /* 0=unlocked, 1=locked */
/* a <cond, mutex> pair to handle an acquire of a locked lock */
pth_cond_t lock_released;
pth_mutex_t mut;
} pth_lock;
#define CHECK_STATUS(name) if (status == -1) { printf("%d ", status); perror(name); error = 1; }
@ -38,10 +38,10 @@ pth_attr_t PyThread_attr;
static void PyThread__init_thread(void)
{
pth_init();
PyThread_attr = pth_attr_new();
pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18);
pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE);
pth_init();
PyThread_attr = pth_attr_new();
pth_attr_set(PyThread_attr, PTH_ATTR_STACK_SIZE, 1<<18);
pth_attr_set(PyThread_attr, PTH_ATTR_JOINABLE, FALSE);
}
/*
@ -51,69 +51,69 @@ static void PyThread__init_thread(void)
long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
pth_t th;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
pth_t th;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
th = pth_spawn(PyThread_attr,
(void* (*)(void *))func,
(void *)arg
);
th = pth_spawn(PyThread_attr,
(void* (*)(void *))func,
(void *)arg
);
return th;
return th;
}
long PyThread_get_thread_ident(void)
{
volatile pth_t threadid;
if (!initialized)
PyThread_init_thread();
/* Jump through some hoops for Alpha OSF/1 */
threadid = pth_self();
return (long) *(long *) &threadid;
volatile pth_t threadid;
if (!initialized)
PyThread_init_thread();
/* Jump through some hoops for Alpha OSF/1 */
threadid = pth_self();
return (long) *(long *) &threadid;
}
static void do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized) {
if (no_cleanup)
_exit(0);
else
exit(0);
}
dprintf(("PyThread_exit_thread called\n"));
if (!initialized) {
if (no_cleanup)
_exit(0);
else
exit(0);
}
}
void PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
}
void PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -122,92 +122,92 @@ void PyThread__exit_prog(int status)
*/
PyThread_type_lock PyThread_allocate_lock(void)
{
pth_lock *lock;
int status, error = 0;
pth_lock *lock;
int status, error = 0;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock = (pth_lock *) malloc(sizeof(pth_lock));
memset((void *)lock, '\0', sizeof(pth_lock));
if (lock) {
lock->locked = 0;
status = pth_mutex_init(&lock->mut);
CHECK_STATUS("pth_mutex_init");
status = pth_cond_init(&lock->lock_released);
CHECK_STATUS("pth_cond_init");
if (error) {
free((void *)lock);
lock = NULL;
}
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
lock = (pth_lock *) malloc(sizeof(pth_lock));
memset((void *)lock, '\0', sizeof(pth_lock));
if (lock) {
lock->locked = 0;
status = pth_mutex_init(&lock->mut);
CHECK_STATUS("pth_mutex_init");
status = pth_cond_init(&lock->lock_released);
CHECK_STATUS("pth_cond_init");
if (error) {
free((void *)lock);
lock = NULL;
}
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void PyThread_free_lock(PyThread_type_lock lock)
{
pth_lock *thelock = (pth_lock *)lock;
pth_lock *thelock = (pth_lock *)lock;
dprintf(("PyThread_free_lock(%p) called\n", lock));
dprintf(("PyThread_free_lock(%p) called\n", lock));
free((void *)thelock);
free((void *)thelock);
}
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
pth_lock *thelock = (pth_lock *)lock;
int status, error = 0;
int success;
pth_lock *thelock = (pth_lock *)lock;
int status, error = 0;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
CHECK_STATUS("pth_mutex_acquire[1]");
success = thelock->locked == 0;
if (success) thelock->locked = 1;
status = pth_mutex_release( &thelock->mut );
CHECK_STATUS("pth_mutex_release[1]");
status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
CHECK_STATUS("pth_mutex_acquire[1]");
success = thelock->locked == 0;
if (success) thelock->locked = 1;
status = pth_mutex_release( &thelock->mut );
CHECK_STATUS("pth_mutex_release[1]");
if ( !success && waitflag ) {
/* continue trying until we get the lock */
if ( !success && waitflag ) {
/* continue trying until we get the lock */
/* mut must be locked by me -- part of the condition
* protocol */
status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
CHECK_STATUS("pth_mutex_acquire[2]");
while ( thelock->locked ) {
status = pth_cond_await(&thelock->lock_released,
&thelock->mut, NULL);
CHECK_STATUS("pth_cond_await");
}
thelock->locked = 1;
status = pth_mutex_release( &thelock->mut );
CHECK_STATUS("pth_mutex_release[2]");
success = 1;
/* mut must be locked by me -- part of the condition
* protocol */
status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
CHECK_STATUS("pth_mutex_acquire[2]");
while ( thelock->locked ) {
status = pth_cond_await(&thelock->lock_released,
&thelock->mut, NULL);
CHECK_STATUS("pth_cond_await");
}
if (error) success = 0;
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
thelock->locked = 1;
status = pth_mutex_release( &thelock->mut );
CHECK_STATUS("pth_mutex_release[2]");
success = 1;
}
if (error) success = 0;
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void PyThread_release_lock(PyThread_type_lock lock)
{
pth_lock *thelock = (pth_lock *)lock;
int status, error = 0;
pth_lock *thelock = (pth_lock *)lock;
int status, error = 0;
dprintf(("PyThread_release_lock(%p) called\n", lock));
dprintf(("PyThread_release_lock(%p) called\n", lock));
status = pth_mutex_acquire( &thelock->mut, 0, NULL );
CHECK_STATUS("pth_mutex_acquire[3]");
status = pth_mutex_acquire( &thelock->mut, 0, NULL );
CHECK_STATUS("pth_mutex_acquire[3]");
thelock->locked = 0;
thelock->locked = 0;
status = pth_mutex_release( &thelock->mut );
CHECK_STATUS("pth_mutex_release[3]");
status = pth_mutex_release( &thelock->mut );
CHECK_STATUS("pth_mutex_release[3]");
/* wake up someone (anyone, if any) waiting on the lock */
status = pth_cond_notify( &thelock->lock_released, 0 );
CHECK_STATUS("pth_cond_notify");
/* wake up someone (anyone, if any) waiting on the lock */
status = pth_cond_notify( &thelock->lock_released, 0 );
CHECK_STATUS("pth_cond_notify");
}

View file

@ -16,10 +16,10 @@
be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
#ifndef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE 0 /* use default stack size */
#define THREAD_STACK_SIZE 0 /* use default stack size */
#endif
/* for safety, ensure a viable minimum stacksize */
#define THREAD_STACK_MIN 0x8000 /* 32kB */
#define THREAD_STACK_MIN 0x8000 /* 32kB */
#else /* !_POSIX_THREAD_ATTR_STACKSIZE */
#ifdef THREAD_STACK_SIZE
#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
@ -28,9 +28,9 @@
/* The POSIX spec says that implementations supporting the sem_*
family of functions must indicate this by defining
_POSIX_SEMAPHORES. */
_POSIX_SEMAPHORES. */
#ifdef _POSIX_SEMAPHORES
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
we need to add 0 to make it work there as well. */
#if (_POSIX_SEMAPHORES+0) == -1
#define HAVE_BROKEN_POSIX_SEMAPHORES
@ -99,10 +99,10 @@
*/
typedef struct {
char locked; /* 0=unlocked, 1=locked */
/* a <cond, mutex> pair to handle an acquire of a locked lock */
pthread_cond_t lock_released;
pthread_mutex_t mut;
char locked; /* 0=unlocked, 1=locked */
/* a <cond, mutex> pair to handle an acquire of a locked lock */
pthread_cond_t lock_released;
pthread_mutex_t mut;
} pthread_lock;
#define CHECK_STATUS(name) if (status != 0) { perror(name); error = 1; }
@ -120,11 +120,11 @@ void _noop(void)
static void
PyThread__init_thread(void)
{
/* DO AN INIT BY STARTING THE THREAD */
static int dummy = 0;
pthread_t thread1;
pthread_create(&thread1, NULL, (void *) _noop, &dummy);
pthread_join(thread1, NULL);
/* DO AN INIT BY STARTING THE THREAD */
static int dummy = 0;
pthread_t thread1;
pthread_create(&thread1, NULL, (void *) _noop, &dummy);
pthread_join(thread1, NULL);
}
#else /* !_HAVE_BSDI */
@ -133,7 +133,7 @@ static void
PyThread__init_thread(void)
{
#if defined(_AIX) && defined(__GNUC__)
pthread_init();
pthread_init();
#endif
}
@ -147,59 +147,59 @@ PyThread__init_thread(void)
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
pthread_t th;
int status;
pthread_t th;
int status;
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
pthread_attr_t attrs;
pthread_attr_t attrs;
#endif
#if defined(THREAD_STACK_SIZE)
size_t tss;
size_t tss;
#endif
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
if (pthread_attr_init(&attrs) != 0)
return -1;
if (pthread_attr_init(&attrs) != 0)
return -1;
#endif
#if defined(THREAD_STACK_SIZE)
tss = (_pythread_stacksize != 0) ? _pythread_stacksize
: THREAD_STACK_SIZE;
if (tss != 0) {
if (pthread_attr_setstacksize(&attrs, tss) != 0) {
pthread_attr_destroy(&attrs);
return -1;
}
}
tss = (_pythread_stacksize != 0) ? _pythread_stacksize
: THREAD_STACK_SIZE;
if (tss != 0) {
if (pthread_attr_setstacksize(&attrs, tss) != 0) {
pthread_attr_destroy(&attrs);
return -1;
}
}
#endif
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
#endif
status = pthread_create(&th,
status = pthread_create(&th,
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
&attrs,
&attrs,
#else
(pthread_attr_t*)NULL,
(pthread_attr_t*)NULL,
#endif
(void* (*)(void *))func,
(void *)arg
);
(void* (*)(void *))func,
(void *)arg
);
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
pthread_attr_destroy(&attrs);
pthread_attr_destroy(&attrs);
#endif
if (status != 0)
return -1;
if (status != 0)
return -1;
pthread_detach(th);
pthread_detach(th);
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
return (long) th;
return (long) th;
#else
return (long) *(long *) &th;
return (long) *(long *) &th;
#endif
}
@ -210,67 +210,67 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
- It is not clear that the 'volatile' (for AIX?) and ugly casting in the
latter return statement (for Alpha OSF/1) are any longer necessary.
*/
long
long
PyThread_get_thread_ident(void)
{
volatile pthread_t threadid;
if (!initialized)
PyThread_init_thread();
/* Jump through some hoops for Alpha OSF/1 */
threadid = pthread_self();
volatile pthread_t threadid;
if (!initialized)
PyThread_init_thread();
/* Jump through some hoops for Alpha OSF/1 */
threadid = pthread_self();
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
return (long) threadid;
return (long) threadid;
#else
return (long) *(long *) &threadid;
return (long) *(long *) &threadid;
#endif
}
static void
static void
do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized) {
if (no_cleanup)
_exit(0);
else
exit(0);
}
dprintf(("PyThread_exit_thread called\n"));
if (!initialized) {
if (no_cleanup)
_exit(0);
else
exit(0);
}
}
void
void
PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void
void
PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void
static void
do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
}
void
void
PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void
void
PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -280,47 +280,47 @@ PyThread__exit_prog(int status)
* Lock support.
*/
PyThread_type_lock
PyThread_type_lock
PyThread_allocate_lock(void)
{
sem_t *lock;
int status, error = 0;
sem_t *lock;
int status, error = 0;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock = (sem_t *)malloc(sizeof(sem_t));
lock = (sem_t *)malloc(sizeof(sem_t));
if (lock) {
status = sem_init(lock,0,1);
CHECK_STATUS("sem_init");
if (lock) {
status = sem_init(lock,0,1);
CHECK_STATUS("sem_init");
if (error) {
free((void *)lock);
lock = NULL;
}
}
if (error) {
free((void *)lock);
lock = NULL;
}
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock)lock;
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock)lock;
}
void
void
PyThread_free_lock(PyThread_type_lock lock)
{
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
dprintf(("PyThread_free_lock(%p) called\n", lock));
dprintf(("PyThread_free_lock(%p) called\n", lock));
if (!thelock)
return;
if (!thelock)
return;
status = sem_destroy(thelock);
CHECK_STATUS("sem_destroy");
status = sem_destroy(thelock);
CHECK_STATUS("sem_destroy");
free((void *)thelock);
free((void *)thelock);
}
/*
@ -332,47 +332,47 @@ PyThread_free_lock(PyThread_type_lock lock)
static int
fix_status(int status)
{
return (status == -1) ? errno : status;
return (status == -1) ? errno : status;
}
int
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
int success;
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
do {
if (waitflag)
status = fix_status(sem_wait(thelock));
else
status = fix_status(sem_trywait(thelock));
} while (status == EINTR); /* Retry if interrupted by a signal */
do {
if (waitflag)
status = fix_status(sem_wait(thelock));
else
status = fix_status(sem_trywait(thelock));
} while (status == EINTR); /* Retry if interrupted by a signal */
if (waitflag) {
CHECK_STATUS("sem_wait");
} else if (status != EAGAIN) {
CHECK_STATUS("sem_trywait");
}
success = (status == 0) ? 1 : 0;
if (waitflag) {
CHECK_STATUS("sem_wait");
} else if (status != EAGAIN) {
CHECK_STATUS("sem_trywait");
}
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
success = (status == 0) ? 1 : 0;
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void
void
PyThread_release_lock(PyThread_type_lock lock)
{
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
sem_t *thelock = (sem_t *)lock;
int status, error = 0;
dprintf(("PyThread_release_lock(%p) called\n", lock));
dprintf(("PyThread_release_lock(%p) called\n", lock));
status = sem_post(thelock);
CHECK_STATUS("sem_post");
status = sem_post(thelock);
CHECK_STATUS("sem_post");
}
#else /* USE_SEMAPHORES */
@ -380,109 +380,109 @@ PyThread_release_lock(PyThread_type_lock lock)
/*
* Lock support.
*/
PyThread_type_lock
PyThread_type_lock
PyThread_allocate_lock(void)
{
pthread_lock *lock;
int status, error = 0;
pthread_lock *lock;
int status, error = 0;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock = (pthread_lock *) malloc(sizeof(pthread_lock));
if (lock) {
memset((void *)lock, '\0', sizeof(pthread_lock));
lock->locked = 0;
lock = (pthread_lock *) malloc(sizeof(pthread_lock));
if (lock) {
memset((void *)lock, '\0', sizeof(pthread_lock));
lock->locked = 0;
status = pthread_mutex_init(&lock->mut,
pthread_mutexattr_default);
CHECK_STATUS("pthread_mutex_init");
status = pthread_mutex_init(&lock->mut,
pthread_mutexattr_default);
CHECK_STATUS("pthread_mutex_init");
status = pthread_cond_init(&lock->lock_released,
pthread_condattr_default);
CHECK_STATUS("pthread_cond_init");
status = pthread_cond_init(&lock->lock_released,
pthread_condattr_default);
CHECK_STATUS("pthread_cond_init");
if (error) {
free((void *)lock);
lock = 0;
}
}
if (error) {
free((void *)lock);
lock = 0;
}
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void
void
PyThread_free_lock(PyThread_type_lock lock)
{
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
dprintf(("PyThread_free_lock(%p) called\n", lock));
dprintf(("PyThread_free_lock(%p) called\n", lock));
status = pthread_mutex_destroy( &thelock->mut );
CHECK_STATUS("pthread_mutex_destroy");
status = pthread_mutex_destroy( &thelock->mut );
CHECK_STATUS("pthread_mutex_destroy");
status = pthread_cond_destroy( &thelock->lock_released );
CHECK_STATUS("pthread_cond_destroy");
status = pthread_cond_destroy( &thelock->lock_released );
CHECK_STATUS("pthread_cond_destroy");
free((void *)thelock);
free((void *)thelock);
}
int
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
int success;
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS("pthread_mutex_lock[1]");
success = thelock->locked == 0;
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS("pthread_mutex_lock[1]");
success = thelock->locked == 0;
if ( !success && waitflag ) {
/* continue trying until we get the lock */
if ( !success && waitflag ) {
/* continue trying until we get the lock */
/* mut must be locked by me -- part of the condition
* protocol */
while ( thelock->locked ) {
status = pthread_cond_wait(&thelock->lock_released,
&thelock->mut);
CHECK_STATUS("pthread_cond_wait");
}
success = 1;
}
if (success) thelock->locked = 1;
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS("pthread_mutex_unlock[1]");
/* mut must be locked by me -- part of the condition
* protocol */
while ( thelock->locked ) {
status = pthread_cond_wait(&thelock->lock_released,
&thelock->mut);
CHECK_STATUS("pthread_cond_wait");
}
success = 1;
}
if (success) thelock->locked = 1;
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS("pthread_mutex_unlock[1]");
if (error) success = 0;
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
if (error) success = 0;
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void
void
PyThread_release_lock(PyThread_type_lock lock)
{
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
dprintf(("PyThread_release_lock(%p) called\n", lock));
dprintf(("PyThread_release_lock(%p) called\n", lock));
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS("pthread_mutex_lock[3]");
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS("pthread_mutex_lock[3]");
thelock->locked = 0;
thelock->locked = 0;
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS("pthread_mutex_unlock[3]");
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS("pthread_mutex_unlock[3]");
/* wake up someone (anyone, if any) waiting on the lock */
status = pthread_cond_signal( &thelock->lock_released );
CHECK_STATUS("pthread_cond_signal");
/* wake up someone (anyone, if any) waiting on the lock */
status = pthread_cond_signal( &thelock->lock_released );
CHECK_STATUS("pthread_cond_signal");
}
#endif /* USE_SEMAPHORES */
@ -495,39 +495,39 @@ static int
_pythread_pthread_set_stacksize(size_t size)
{
#if defined(THREAD_STACK_SIZE)
pthread_attr_t attrs;
size_t tss_min;
int rc = 0;
pthread_attr_t attrs;
size_t tss_min;
int rc = 0;
#endif
/* set to default */
if (size == 0) {
_pythread_stacksize = 0;
return 0;
}
/* set to default */
if (size == 0) {
_pythread_stacksize = 0;
return 0;
}
#if defined(THREAD_STACK_SIZE)
#if defined(PTHREAD_STACK_MIN)
tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
: THREAD_STACK_MIN;
tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
: THREAD_STACK_MIN;
#else
tss_min = THREAD_STACK_MIN;
tss_min = THREAD_STACK_MIN;
#endif
if (size >= tss_min) {
/* validate stack size by setting thread attribute */
if (pthread_attr_init(&attrs) == 0) {
rc = pthread_attr_setstacksize(&attrs, size);
pthread_attr_destroy(&attrs);
if (rc == 0) {
_pythread_stacksize = size;
return 0;
}
}
}
return -1;
if (size >= tss_min) {
/* validate stack size by setting thread attribute */
if (pthread_attr_init(&attrs) == 0) {
rc = pthread_attr_setstacksize(&attrs, size);
pthread_attr_destroy(&attrs);
if (rc == 0) {
_pythread_stacksize = size;
return 0;
}
}
}
return -1;
#else
return -2;
return -2;
#endif
}
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)

View file

@ -8,25 +8,25 @@
#include <ulocks.h>
#include <errno.h>
#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
#define MAXPROC 100 /* max # of threads that can be started */
#define HDR_SIZE 2680 /* sizeof(ushdr_t) */
#define MAXPROC 100 /* max # of threads that can be started */
static usptr_t *shared_arena;
static ulock_t count_lock; /* protection for some variables */
static ulock_t wait_lock; /* lock used to wait for other threads */
static int waiting_for_threads; /* protected by count_lock */
static int nthreads; /* protected by count_lock */
static ulock_t count_lock; /* protection for some variables */
static ulock_t wait_lock; /* lock used to wait for other threads */
static int waiting_for_threads; /* protected by count_lock */
static int nthreads; /* protected by count_lock */
static int exit_status;
#ifndef NO_EXIT_PROG
static int do_exit; /* indicates that the program is to exit */
static int do_exit; /* indicates that the program is to exit */
#endif
static int exiting; /* we're already exiting (for maybe_exit) */
static pid_t my_pid; /* PID of main thread */
static int exiting; /* we're already exiting (for maybe_exit) */
static pid_t my_pid; /* PID of main thread */
static struct pidlist {
pid_t parent;
pid_t child;
} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
static int maxpidindex; /* # of PIDs in pidlist */
pid_t parent;
pid_t child;
} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */
static int maxpidindex; /* # of PIDs in pidlist */
#ifndef NO_EXIT_PROG
/*
@ -36,19 +36,19 @@ static int maxpidindex; /* # of PIDs in pidlist */
*/
static void exit_sig(void)
{
d2printf(("exit_sig called\n"));
if (exiting && getpid() == my_pid) {
d2printf(("already exiting\n"));
return;
}
if (do_exit) {
d2printf(("exiting in exit_sig\n"));
d2printf(("exit_sig called\n"));
if (exiting && getpid() == my_pid) {
d2printf(("already exiting\n"));
return;
}
if (do_exit) {
d2printf(("exiting in exit_sig\n"));
#ifdef Py_DEBUG
if ((thread_debug & 8) == 0)
thread_debug &= ~1; /* don't produce debug messages */
if ((thread_debug & 8) == 0)
thread_debug &= ~1; /* don't produce debug messages */
#endif
PyThread_exit_thread();
}
PyThread_exit_thread();
}
}
/*
@ -57,12 +57,12 @@ static void exit_sig(void)
*/
static void maybe_exit(void)
{
dprintf(("maybe_exit called\n"));
if (exiting) {
dprintf(("already exiting\n"));
return;
}
PyThread_exit_prog(0);
dprintf(("maybe_exit called\n"));
if (exiting) {
dprintf(("already exiting\n"));
return;
}
PyThread_exit_prog(0);
}
#endif /* NO_EXIT_PROG */
@ -72,58 +72,58 @@ static void maybe_exit(void)
static void PyThread__init_thread(void)
{
#ifndef NO_EXIT_PROG
struct sigaction s;
struct sigaction s;
#endif /* NO_EXIT_PROG */
#ifdef USE_DL
long addr, size;
long addr, size;
#endif /* USE_DL */
#ifdef USE_DL
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
perror("usconfig - CONF_INITSIZE (check)");
if (usconfig(CONF_INITSIZE, size) < 0)
perror("usconfig - CONF_INITSIZE (reset)");
addr = (long) dl_getrange(size + HDR_SIZE);
dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
errno = 0;
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
perror("usconfig - CONF_ATTACHADDR (set)");
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
perror("usconfig - CONF_INITSIZE (check)");
if (usconfig(CONF_INITSIZE, size) < 0)
perror("usconfig - CONF_INITSIZE (reset)");
addr = (long) dl_getrange(size + HDR_SIZE);
dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
errno = 0;
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
perror("usconfig - CONF_ATTACHADDR (set)");
#endif /* USE_DL */
if (usconfig(CONF_INITUSERS, 16) < 0)
perror("usconfig - CONF_INITUSERS");
my_pid = getpid(); /* so that we know which is the main thread */
if (usconfig(CONF_INITUSERS, 16) < 0)
perror("usconfig - CONF_INITUSERS");
my_pid = getpid(); /* so that we know which is the main thread */
#ifndef NO_EXIT_PROG
atexit(maybe_exit);
s.sa_handler = exit_sig;
sigemptyset(&s.sa_mask);
/*sigaddset(&s.sa_mask, SIGUSR1);*/
s.sa_flags = 0;
sigaction(SIGUSR1, &s, 0);
if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
perror("prctl - PR_SETEXITSIG");
atexit(maybe_exit);
s.sa_handler = exit_sig;
sigemptyset(&s.sa_mask);
/*sigaddset(&s.sa_mask, SIGUSR1);*/
s.sa_flags = 0;
sigaction(SIGUSR1, &s, 0);
if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
perror("prctl - PR_SETEXITSIG");
#endif /* NO_EXIT_PROG */
if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
perror("usconfig - CONF_ARENATYPE");
usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
perror("usconfig - CONF_ARENATYPE");
usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
#ifdef Py_DEBUG
if (thread_debug & 4)
usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
else if (thread_debug & 2)
usconfig(CONF_LOCKTYPE, US_DEBUG);
if (thread_debug & 4)
usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
else if (thread_debug & 2)
usconfig(CONF_LOCKTYPE, US_DEBUG);
#endif /* Py_DEBUG */
if ((shared_arena = usinit(tmpnam(0))) == 0)
perror("usinit");
if ((shared_arena = usinit(tmpnam(0))) == 0)
perror("usinit");
#ifdef USE_DL
if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
perror("usconfig - CONF_ATTACHADDR (reset)");
if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
perror("usconfig - CONF_ATTACHADDR (reset)");
#endif /* USE_DL */
if ((count_lock = usnewlock(shared_arena)) == NULL)
perror("usnewlock (count_lock)");
(void) usinitlock(count_lock);
if ((wait_lock = usnewlock(shared_arena)) == NULL)
perror("usnewlock (wait_lock)");
dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
if ((count_lock = usnewlock(shared_arena)) == NULL)
perror("usnewlock (count_lock)");
(void) usinitlock(count_lock);
if ((wait_lock = usnewlock(shared_arena)) == NULL)
perror("usnewlock (wait_lock)");
dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
}
/*
@ -132,198 +132,198 @@ static void PyThread__init_thread(void)
static void clean_threads(void)
{
int i, j;
pid_t mypid, pid;
int i, j;
pid_t mypid, pid;
/* clean up any exited threads */
mypid = getpid();
i = 0;
while (i < maxpidindex) {
if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
pid = waitpid(pid, 0, WNOHANG);
if (pid > 0) {
/* a thread has exited */
pidlist[i] = pidlist[--maxpidindex];
/* remove references to children of dead proc */
for (j = 0; j < maxpidindex; j++)
if (pidlist[j].parent == pid)
pidlist[j].child = -1;
continue; /* don't increment i */
}
}
i++;
}
/* clean up the list */
i = 0;
while (i < maxpidindex) {
if (pidlist[i].child == -1) {
pidlist[i] = pidlist[--maxpidindex];
continue; /* don't increment i */
}
i++;
}
/* clean up any exited threads */
mypid = getpid();
i = 0;
while (i < maxpidindex) {
if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
pid = waitpid(pid, 0, WNOHANG);
if (pid > 0) {
/* a thread has exited */
pidlist[i] = pidlist[--maxpidindex];
/* remove references to children of dead proc */
for (j = 0; j < maxpidindex; j++)
if (pidlist[j].parent == pid)
pidlist[j].child = -1;
continue; /* don't increment i */
}
}
i++;
}
/* clean up the list */
i = 0;
while (i < maxpidindex) {
if (pidlist[i].child == -1) {
pidlist[i] = pidlist[--maxpidindex];
continue; /* don't increment i */
}
i++;
}
}
long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
#ifdef USE_DL
long addr, size;
static int local_initialized = 0;
long addr, size;
static int local_initialized = 0;
#endif /* USE_DL */
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
switch (ussetlock(count_lock)) {
case 0: return 0;
case -1: perror("ussetlock (count_lock)");
}
if (maxpidindex >= MAXPROC)
success = -1;
else {
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
switch (ussetlock(count_lock)) {
case 0: return 0;
case -1: perror("ussetlock (count_lock)");
}
if (maxpidindex >= MAXPROC)
success = -1;
else {
#ifdef USE_DL
if (!local_initialized) {
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
perror("usconfig - CONF_INITSIZE (check)");
if (usconfig(CONF_INITSIZE, size) < 0)
perror("usconfig - CONF_INITSIZE (reset)");
addr = (long) dl_getrange(size + HDR_SIZE);
dprintf(("trying to use addr %p-%p for sproc\n",
addr, addr+size));
errno = 0;
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
errno != 0)
perror("usconfig - CONF_ATTACHADDR (set)");
}
if (!local_initialized) {
if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
perror("usconfig - CONF_INITSIZE (check)");
if (usconfig(CONF_INITSIZE, size) < 0)
perror("usconfig - CONF_INITSIZE (reset)");
addr = (long) dl_getrange(size + HDR_SIZE);
dprintf(("trying to use addr %p-%p for sproc\n",
addr, addr+size));
errno = 0;
if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
errno != 0)
perror("usconfig - CONF_ATTACHADDR (set)");
}
#endif /* USE_DL */
clean_threads();
if ((success = sproc(func, PR_SALL, arg)) < 0)
perror("sproc");
clean_threads();
if ((success = sproc(func, PR_SALL, arg)) < 0)
perror("sproc");
#ifdef USE_DL
if (!local_initialized) {
if (usconfig(CONF_ATTACHADDR, addr) < 0)
/* reset address */
perror("usconfig - CONF_ATTACHADDR (reset)");
local_initialized = 1;
}
if (!local_initialized) {
if (usconfig(CONF_ATTACHADDR, addr) < 0)
/* reset address */
perror("usconfig - CONF_ATTACHADDR (reset)");
local_initialized = 1;
}
#endif /* USE_DL */
if (success >= 0) {
nthreads++;
pidlist[maxpidindex].parent = getpid();
pidlist[maxpidindex++].child = success;
dprintf(("pidlist[%d] = %d\n",
maxpidindex-1, success));
}
}
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
return success;
if (success >= 0) {
nthreads++;
pidlist[maxpidindex].parent = getpid();
pidlist[maxpidindex++].child = success;
dprintf(("pidlist[%d] = %d\n",
maxpidindex-1, success));
}
}
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
return success;
}
long PyThread_get_thread_ident(void)
{
return getpid();
return getpid();
}
static void do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
if (ussetlock(count_lock) < 0)
perror("ussetlock (count_lock)");
nthreads--;
if (getpid() == my_pid) {
/* main thread; wait for other threads to exit */
exiting = 1;
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
if (ussetlock(count_lock) < 0)
perror("ussetlock (count_lock)");
nthreads--;
if (getpid() == my_pid) {
/* main thread; wait for other threads to exit */
exiting = 1;
#ifndef NO_EXIT_PROG
if (do_exit) {
int i;
if (do_exit) {
int i;
/* notify other threads */
clean_threads();
if (nthreads >= 0) {
dprintf(("kill other threads\n"));
for (i = 0; i < maxpidindex; i++)
if (pidlist[i].child > 0)
(void) kill(pidlist[i].child,
SIGKILL);
_exit(exit_status);
}
}
/* notify other threads */
clean_threads();
if (nthreads >= 0) {
dprintf(("kill other threads\n"));
for (i = 0; i < maxpidindex; i++)
if (pidlist[i].child > 0)
(void) kill(pidlist[i].child,
SIGKILL);
_exit(exit_status);
}
}
#endif /* NO_EXIT_PROG */
waiting_for_threads = 1;
if (ussetlock(wait_lock) < 0)
perror("ussetlock (wait_lock)");
for (;;) {
if (nthreads < 0) {
dprintf(("really exit (%d)\n", exit_status));
if (no_cleanup)
_exit(exit_status);
else
exit(exit_status);
}
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
dprintf(("waiting for other threads (%d)\n", nthreads));
if (ussetlock(wait_lock) < 0)
perror("ussetlock (wait_lock)");
if (ussetlock(count_lock) < 0)
perror("ussetlock (count_lock)");
}
}
/* not the main thread */
if (waiting_for_threads) {
dprintf(("main thread is waiting\n"));
if (usunsetlock(wait_lock) < 0)
perror("usunsetlock (wait_lock)");
}
waiting_for_threads = 1;
if (ussetlock(wait_lock) < 0)
perror("ussetlock (wait_lock)");
for (;;) {
if (nthreads < 0) {
dprintf(("really exit (%d)\n", exit_status));
if (no_cleanup)
_exit(exit_status);
else
exit(exit_status);
}
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
dprintf(("waiting for other threads (%d)\n", nthreads));
if (ussetlock(wait_lock) < 0)
perror("ussetlock (wait_lock)");
if (ussetlock(count_lock) < 0)
perror("ussetlock (count_lock)");
}
}
/* not the main thread */
if (waiting_for_threads) {
dprintf(("main thread is waiting\n"));
if (usunsetlock(wait_lock) < 0)
perror("usunsetlock (wait_lock)");
}
#ifndef NO_EXIT_PROG
else if (do_exit)
(void) kill(my_pid, SIGUSR1);
else if (do_exit)
(void) kill(my_pid, SIGUSR1);
#endif /* NO_EXIT_PROG */
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
_exit(0);
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
_exit(0);
}
void PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
do_exit = 1;
exit_status = status;
do_PyThread_exit_thread(no_cleanup);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
do_exit = 1;
exit_status = status;
do_PyThread_exit_thread(no_cleanup);
}
void PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -332,44 +332,44 @@ void PyThread__exit_prog(int status)
*/
PyThread_type_lock PyThread_allocate_lock(void)
{
ulock_t lock;
ulock_t lock;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
if ((lock = usnewlock(shared_arena)) == NULL)
perror("usnewlock");
(void) usinitlock(lock);
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
if ((lock = usnewlock(shared_arena)) == NULL)
perror("usnewlock");
(void) usinitlock(lock);
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void PyThread_free_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_free_lock(%p) called\n", lock));
usfreelock((ulock_t) lock, shared_arena);
dprintf(("PyThread_free_lock(%p) called\n", lock));
usfreelock((ulock_t) lock, shared_arena);
}
int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
int success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
errno = 0; /* clear it just in case */
if (waitflag)
success = ussetlock((ulock_t) lock);
else
success = uscsetlock((ulock_t) lock, 1); /* Try it once */
if (success < 0)
perror(waitflag ? "ussetlock" : "uscsetlock");
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
errno = 0; /* clear it just in case */
if (waitflag)
success = ussetlock((ulock_t) lock);
else
success = uscsetlock((ulock_t) lock, 1); /* Try it once */
if (success < 0)
perror(waitflag ? "ussetlock" : "uscsetlock");
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void PyThread_release_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_release_lock(%p) called\n", lock));
if (usunsetlock((ulock_t) lock) < 0)
perror("usunsetlock");
dprintf(("PyThread_release_lock(%p) called\n", lock));
if (usunsetlock((ulock_t) lock) < 0)
perror("usunsetlock");
}

View file

@ -17,158 +17,158 @@ static void PyThread__init_thread(void)
* Thread support.
*/
struct func_arg {
void (*func)(void *);
void *arg;
void (*func)(void *);
void *arg;
};
static void *
new_func(void *funcarg)
{
void (*func)(void *);
void *arg;
void (*func)(void *);
void *arg;
func = ((struct func_arg *) funcarg)->func;
arg = ((struct func_arg *) funcarg)->arg;
free(funcarg);
(*func)(arg);
return 0;
func = ((struct func_arg *) funcarg)->func;
arg = ((struct func_arg *) funcarg)->arg;
free(funcarg);
(*func)(arg);
return 0;
}
long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
thread_t tid;
struct func_arg *funcarg;
thread_t tid;
struct func_arg *funcarg;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
funcarg->func = func;
funcarg->arg = arg;
if (thr_create(0, 0, new_func, funcarg,
THR_DETACHED | THR_NEW_LWP, &tid)) {
perror("thr_create");
free((void *) funcarg);
return -1;
}
return tid;
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
funcarg->func = func;
funcarg->arg = arg;
if (thr_create(0, 0, new_func, funcarg,
THR_DETACHED | THR_NEW_LWP, &tid)) {
perror("thr_create");
free((void *) funcarg);
return -1;
}
return tid;
}
long
PyThread_get_thread_ident(void)
{
if (!initialized)
PyThread_init_thread();
return thr_self();
if (!initialized)
PyThread_init_thread();
return thr_self();
}
static void
static void
do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
thr_exit(0);
dprintf(("PyThread_exit_thread called\n"));
if (!initialized)
if (no_cleanup)
_exit(0);
else
exit(0);
thr_exit(0);
}
void
void
PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void
void
PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void
static void
do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
if (no_cleanup)
_exit(status);
else
exit(status);
}
void
void
PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void
void
PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
/*
* Lock support.
*/
PyThread_type_lock
PyThread_type_lock
PyThread_allocate_lock(void)
{
mutex_t *lock;
mutex_t *lock;
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
lock = (mutex_t *) malloc(sizeof(mutex_t));
if (mutex_init(lock, USYNC_THREAD, 0)) {
perror("mutex_init");
free((void *) lock);
lock = 0;
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
lock = (mutex_t *) malloc(sizeof(mutex_t));
if (mutex_init(lock, USYNC_THREAD, 0)) {
perror("mutex_init");
free((void *) lock);
lock = 0;
}
dprintf(("PyThread_allocate_lock() -> %p\n", lock));
return (PyThread_type_lock) lock;
}
void
void
PyThread_free_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_free_lock(%p) called\n", lock));
mutex_destroy((mutex_t *) lock);
free((void *) lock);
dprintf(("PyThread_free_lock(%p) called\n", lock));
mutex_destroy((mutex_t *) lock);
free((void *) lock);
}
int
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
int success;
int success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
if (waitflag)
success = mutex_lock((mutex_t *) lock);
else
success = mutex_trylock((mutex_t *) lock);
if (success < 0)
perror(waitflag ? "mutex_lock" : "mutex_trylock");
else
success = !success; /* solaris does it the other way round */
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
if (waitflag)
success = mutex_lock((mutex_t *) lock);
else
success = mutex_trylock((mutex_t *) lock);
if (success < 0)
perror(waitflag ? "mutex_lock" : "mutex_trylock");
else
success = !success; /* solaris does it the other way round */
dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
return success;
}
void
void
PyThread_release_lock(PyThread_type_lock lock)
{
dprintf(("PyThread_release_lock(%p) called\n", lock));
if (mutex_unlock((mutex_t *) lock))
perror("mutex_unlock");
dprintf(("PyThread_release_lock(%p) called\n", lock));
if (mutex_unlock((mutex_t *) lock))
perror("mutex_unlock");
}

View file

@ -24,21 +24,21 @@ static void PyThread__init_thread(void)
*/
long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
long rv;
int success = -1;
long rv;
int success = -1;
dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
PyThread_init_thread();
dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
PyThread_init_thread();
rv = _beginthread(func, 0, arg); /* use default stack size */
if (rv != -1) {
success = 0;
dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident()));
}
rv = _beginthread(func, 0, arg); /* use default stack size */
return success;
if (rv != -1) {
success = 0;
dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident()));
}
return success;
}
/*
@ -47,52 +47,52 @@ long PyThread_start_new_thread(void (*func)(void *), void *arg)
*/
long PyThread_get_thread_ident(void)
{
if (!initialized)
PyThread_init_thread();
return GetCurrentThreadId();
if (!initialized)
PyThread_init_thread();
return GetCurrentThreadId();
}
static void do_PyThread_exit_thread(int no_cleanup)
{
dprintf(("%ld: do_PyThread_exit_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
if (no_cleanup)
exit(0); /* XXX - was _exit()!! */
else
exit(0);
_endthread();
dprintf(("%ld: do_PyThread_exit_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
if (no_cleanup)
exit(0); /* XXX - was _exit()!! */
else
exit(0);
_endthread();
}
void PyThread_exit_thread(void)
{
do_PyThread_exit_thread(0);
do_PyThread_exit_thread(0);
}
void PyThread__exit_thread(void)
{
do_PyThread_exit_thread(1);
do_PyThread_exit_thread(1);
}
#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog(int status, int no_cleanup)
{
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
dprintf(("PyThread_exit_prog(%d) called\n", status));
if (!initialized)
if (no_cleanup)
_exit(status);
else
exit(status);
}
void PyThread_exit_prog(int status)
{
do_PyThread_exit_prog(status, 0);
do_PyThread_exit_prog(status, 0);
}
void PyThread__exit_prog(int status)
{
do_PyThread_exit_prog(status, 1);
do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */
@ -107,12 +107,12 @@ PyThread_type_lock PyThread_allocate_lock(void)
dprintf(("PyThread_allocate_lock called\n"));
if (!initialized)
PyThread_init_thread();
PyThread_init_thread();
aLock = CreateEvent(NULL, /* Security attributes */
0, /* Manual-Reset */
1, /* Is initially signalled */
NULL); /* Name of event */
0, /* Manual-Reset */
1, /* Is initially signalled */
NULL); /* Name of event */
dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock));
@ -142,22 +142,22 @@ int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag)
#ifndef DEBUG
waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0));
#else
/* To aid in debugging, we regularly wake up. This allows us to
break into the debugger */
while (TRUE) {
waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0);
if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0))
break;
}
/* To aid in debugging, we regularly wake up. This allows us to
break into the debugger */
while (TRUE) {
waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0);
if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0))
break;
}
#endif
if (waitResult != WAIT_OBJECT_0) {
success = 0; /* We failed */
success = 0; /* We failed */
}
dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success));
return success;
return success;
}
void PyThread_release_lock(PyThread_type_lock aLock)
@ -165,7 +165,7 @@ void PyThread_release_lock(PyThread_type_lock aLock)
dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock));
if (!SetEvent(aLock))
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError()));
dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError()));
}

View file

@ -12,274 +12,274 @@
#define OFF(x) offsetof(PyTracebackObject, x)
static PyMemberDef tb_memberlist[] = {
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
{NULL} /* Sentinel */
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
{NULL} /* Sentinel */
};
static void
tb_dealloc(PyTracebackObject *tb)
{
PyObject_GC_UnTrack(tb);
Py_TRASHCAN_SAFE_BEGIN(tb)
Py_XDECREF(tb->tb_next);
Py_XDECREF(tb->tb_frame);
PyObject_GC_Del(tb);
Py_TRASHCAN_SAFE_END(tb)
PyObject_GC_UnTrack(tb);
Py_TRASHCAN_SAFE_BEGIN(tb)
Py_XDECREF(tb->tb_next);
Py_XDECREF(tb->tb_frame);
PyObject_GC_Del(tb);
Py_TRASHCAN_SAFE_END(tb)
}
static int
tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
{
Py_VISIT(tb->tb_next);
Py_VISIT(tb->tb_frame);
return 0;
Py_VISIT(tb->tb_next);
Py_VISIT(tb->tb_frame);
return 0;
}
static void
tb_clear(PyTracebackObject *tb)
{
Py_CLEAR(tb->tb_next);
Py_CLEAR(tb->tb_frame);
Py_CLEAR(tb->tb_next);
Py_CLEAR(tb->tb_frame);
}
PyTypeObject PyTraceBack_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"traceback",
sizeof(PyTracebackObject),
0,
(destructor)tb_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)tb_traverse, /* tp_traverse */
(inquiry)tb_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
tb_memberlist, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"traceback",
sizeof(PyTracebackObject),
0,
(destructor)tb_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
0, /* tp_doc */
(traverseproc)tb_traverse, /* tp_traverse */
(inquiry)tb_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
tb_memberlist, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
};
static PyTracebackObject *
newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
{
PyTracebackObject *tb;
if ((next != NULL && !PyTraceBack_Check(next)) ||
frame == NULL || !PyFrame_Check(frame)) {
PyErr_BadInternalCall();
return NULL;
}
tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
if (tb != NULL) {
Py_XINCREF(next);
tb->tb_next = next;
Py_XINCREF(frame);
tb->tb_frame = frame;
tb->tb_lasti = frame->f_lasti;
tb->tb_lineno = PyCode_Addr2Line(frame->f_code,
frame->f_lasti);
PyObject_GC_Track(tb);
}
return tb;
PyTracebackObject *tb;
if ((next != NULL && !PyTraceBack_Check(next)) ||
frame == NULL || !PyFrame_Check(frame)) {
PyErr_BadInternalCall();
return NULL;
}
tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
if (tb != NULL) {
Py_XINCREF(next);
tb->tb_next = next;
Py_XINCREF(frame);
tb->tb_frame = frame;
tb->tb_lasti = frame->f_lasti;
tb->tb_lineno = PyCode_Addr2Line(frame->f_code,
frame->f_lasti);
PyObject_GC_Track(tb);
}
return tb;
}
int
PyTraceBack_Here(PyFrameObject *frame)
{
PyThreadState *tstate = PyThreadState_GET();
PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
PyTracebackObject *tb = newtracebackobject(oldtb, frame);
if (tb == NULL)
return -1;
tstate->curexc_traceback = (PyObject *)tb;
Py_XDECREF(oldtb);
return 0;
PyThreadState *tstate = PyThreadState_GET();
PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
PyTracebackObject *tb = newtracebackobject(oldtb, frame);
if (tb == NULL)
return -1;
tstate->curexc_traceback = (PyObject *)tb;
Py_XDECREF(oldtb);
return 0;
}
int
_Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent)
{
int err = 0;
FILE *xfp = NULL;
char linebuf[2000];
int i;
char namebuf[MAXPATHLEN+1];
int err = 0;
FILE *xfp = NULL;
char linebuf[2000];
int i;
char namebuf[MAXPATHLEN+1];
if (filename == NULL)
return -1;
/* This is needed by Emacs' compile command */
if (filename == NULL)
return -1;
/* This is needed by Emacs' compile command */
#define FMT " File \"%.500s\", line %d, in %.500s\n"
xfp = fopen(filename, "r" PY_STDIOTEXTMODE);
if (xfp == NULL) {
/* Search tail of filename in sys.path before giving up */
PyObject *path;
const char *tail = strrchr(filename, SEP);
if (tail == NULL)
tail = filename;
else
tail++;
path = PySys_GetObject("path");
if (path != NULL && PyList_Check(path)) {
Py_ssize_t _npath = PyList_Size(path);
int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
size_t taillen = strlen(tail);
for (i = 0; i < npath; i++) {
PyObject *v = PyList_GetItem(path, i);
if (v == NULL) {
PyErr_Clear();
break;
}
if (PyString_Check(v)) {
size_t len;
len = PyString_GET_SIZE(v);
if (len + 1 + taillen >= MAXPATHLEN)
continue; /* Too long */
strcpy(namebuf, PyString_AsString(v));
if (strlen(namebuf) != len)
continue; /* v contains '\0' */
if (len > 0 && namebuf[len-1] != SEP)
namebuf[len++] = SEP;
strcpy(namebuf+len, tail);
xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE);
if (xfp != NULL) {
filename = namebuf;
break;
}
}
}
}
}
xfp = fopen(filename, "r" PY_STDIOTEXTMODE);
if (xfp == NULL) {
/* Search tail of filename in sys.path before giving up */
PyObject *path;
const char *tail = strrchr(filename, SEP);
if (tail == NULL)
tail = filename;
else
tail++;
path = PySys_GetObject("path");
if (path != NULL && PyList_Check(path)) {
Py_ssize_t _npath = PyList_Size(path);
int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
size_t taillen = strlen(tail);
for (i = 0; i < npath; i++) {
PyObject *v = PyList_GetItem(path, i);
if (v == NULL) {
PyErr_Clear();
break;
}
if (PyString_Check(v)) {
size_t len;
len = PyString_GET_SIZE(v);
if (len + 1 + taillen >= MAXPATHLEN)
continue; /* Too long */
strcpy(namebuf, PyString_AsString(v));
if (strlen(namebuf) != len)
continue; /* v contains '\0' */
if (len > 0 && namebuf[len-1] != SEP)
namebuf[len++] = SEP;
strcpy(namebuf+len, tail);
xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE);
if (xfp != NULL) {
filename = namebuf;
break;
}
}
}
}
}
if (xfp == NULL)
return err;
if (err != 0) {
fclose(xfp);
return err;
if (xfp == NULL)
return err;
if (err != 0) {
fclose(xfp);
return err;
}
for (i = 0; i < lineno; i++) {
char* pLastChar = &linebuf[sizeof(linebuf)-2];
do {
*pLastChar = '\0';
if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL)
break;
/* fgets read *something*; if it didn't get as
far as pLastChar, it must have found a newline
or hit the end of the file; if pLastChar is \n,
it obviously found a newline; else we haven't
yet seen a newline, so must continue */
} while (*pLastChar != '\0' && *pLastChar != '\n');
}
if (i == lineno) {
char buf[11];
char *p = linebuf;
while (*p == ' ' || *p == '\t' || *p == '\014')
p++;
/* Write some spaces before the line */
strcpy(buf, " ");
assert (strlen(buf) == 10);
while (indent > 0) {
if(indent < 10)
buf[indent] = '\0';
err = PyFile_WriteString(buf, f);
if (err != 0)
break;
indent -= 10;
}
for (i = 0; i < lineno; i++) {
char* pLastChar = &linebuf[sizeof(linebuf)-2];
do {
*pLastChar = '\0';
if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL)
break;
/* fgets read *something*; if it didn't get as
far as pLastChar, it must have found a newline
or hit the end of the file; if pLastChar is \n,
it obviously found a newline; else we haven't
yet seen a newline, so must continue */
} while (*pLastChar != '\0' && *pLastChar != '\n');
}
if (i == lineno) {
char buf[11];
char *p = linebuf;
while (*p == ' ' || *p == '\t' || *p == '\014')
p++;
/* Write some spaces before the line */
strcpy(buf, " ");
assert (strlen(buf) == 10);
while (indent > 0) {
if(indent < 10)
buf[indent] = '\0';
err = PyFile_WriteString(buf, f);
if (err != 0)
break;
indent -= 10;
}
if (err == 0)
err = PyFile_WriteString(p, f);
if (err == 0 && strchr(p, '\n') == NULL)
err = PyFile_WriteString("\n", f);
}
fclose(xfp);
return err;
if (err == 0)
err = PyFile_WriteString(p, f);
if (err == 0 && strchr(p, '\n') == NULL)
err = PyFile_WriteString("\n", f);
}
fclose(xfp);
return err;
}
static int
tb_displayline(PyObject *f, const char *filename, int lineno, const char *name)
{
int err = 0;
char linebuf[2000];
int err = 0;
char linebuf[2000];
if (filename == NULL || name == NULL)
return -1;
/* This is needed by Emacs' compile command */
if (filename == NULL || name == NULL)
return -1;
/* This is needed by Emacs' compile command */
#define FMT " File \"%.500s\", line %d, in %.500s\n"
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
err = PyFile_WriteString(linebuf, f);
if (err != 0)
return err;
return _Py_DisplaySourceLine(f, filename, lineno, 4);
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
err = PyFile_WriteString(linebuf, f);
if (err != 0)
return err;
return _Py_DisplaySourceLine(f, filename, lineno, 4);
}
static int
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
{
int err = 0;
long depth = 0;
PyTracebackObject *tb1 = tb;
while (tb1 != NULL) {
depth++;
tb1 = tb1->tb_next;
}
while (tb != NULL && err == 0) {
if (depth <= limit) {
err = tb_displayline(f,
PyString_AsString(
tb->tb_frame->f_code->co_filename),
tb->tb_lineno,
PyString_AsString(tb->tb_frame->f_code->co_name));
}
depth--;
tb = tb->tb_next;
if (err == 0)
err = PyErr_CheckSignals();
}
return err;
int err = 0;
long depth = 0;
PyTracebackObject *tb1 = tb;
while (tb1 != NULL) {
depth++;
tb1 = tb1->tb_next;
}
while (tb != NULL && err == 0) {
if (depth <= limit) {
err = tb_displayline(f,
PyString_AsString(
tb->tb_frame->f_code->co_filename),
tb->tb_lineno,
PyString_AsString(tb->tb_frame->f_code->co_name));
}
depth--;
tb = tb->tb_next;
if (err == 0)
err = PyErr_CheckSignals();
}
return err;
}
int
PyTraceBack_Print(PyObject *v, PyObject *f)
{
int err;
PyObject *limitv;
long limit = 1000;
if (v == NULL)
return 0;
if (!PyTraceBack_Check(v)) {
PyErr_BadInternalCall();
return -1;
}
limitv = PySys_GetObject("tracebacklimit");
if (limitv && PyInt_Check(limitv)) {
limit = PyInt_AsLong(limitv);
if (limit <= 0)
return 0;
}
err = PyFile_WriteString("Traceback (most recent call last):\n", f);
if (!err)
err = tb_printinternal((PyTracebackObject *)v, f, limit);
return err;
int err;
PyObject *limitv;
long limit = 1000;
if (v == NULL)
return 0;
if (!PyTraceBack_Check(v)) {
PyErr_BadInternalCall();
return -1;
}
limitv = PySys_GetObject("tracebacklimit");
if (limitv && PyInt_Check(limitv)) {
limit = PyInt_AsLong(limitv);
if (limit <= 0)
return 0;
}
err = PyFile_WriteString("Traceback (most recent call last):\n", f);
if (!err)
err = tb_printinternal((PyTracebackObject *)v, f, limit);
return err;
}