PageRenderTime 192ms CodeModel.GetById 81ms app.highlight 13ms RepoModel.GetById 95ms app.codeStats 0ms

/Python/dynload_beos.c

http://unladen-swallow.googlecode.com/
C | 254 lines | 156 code | 44 blank | 54 comment | 27 complexity | 3221ebba998c0a14d308c9102f980223 MD5 | raw file
  1
  2/* Support for dynamic loading of extension modules */
  3
  4#include <kernel/image.h>
  5#include <kernel/OS.h>
  6#include <stdlib.h>
  7
  8#include "Python.h"
  9#include "importdl.h"
 10
 11const struct filedescr _PyImport_DynLoadFiletab[] = {
 12	{".so", "rb", C_EXTENSION},
 13	{"module.so", "rb", C_EXTENSION},
 14	{0, 0}
 15};
 16
 17#if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
 18#undef MAXPATHLEN
 19#endif
 20
 21#ifdef WITH_THREAD
 22#include "pythread.h"
 23static PyThread_type_lock beos_dyn_lock;
 24#endif
 25
 26static PyObject *beos_dyn_images = NULL;
 27
 28/* ----------------------------------------------------------------------
 29 * BeOS dynamic loading support
 30 *
 31 * This uses shared libraries, but BeOS has its own way of doing things
 32 * (much easier than dlfnc.h, from the look of things).  We'll use a
 33 * Python Dictionary object to store the images_ids so we can be very
 34 * nice and unload them when we exit.
 35 *
 36 * Note that this is thread-safe.  Probably irrelevent, because of losing
 37 * systems... Python probably disables threads while loading modules.
 38 * Note the use of "probably"!  Better to be safe than sorry. [chrish]
 39 *
 40 * As of 1.5.1 this should also work properly when you've configured
 41 * Python without thread support; the 1.5 version required it, which wasn't
 42 * very friendly.  Note that I haven't tested it without threading... why
 43 * would you want to avoid threads on BeOS? [chrish]
 44 *
 45 * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn
 46 * tells me it's not necessary anymore because of PyCObject_Import().
 47 * [chrish]
 48 */
 49
 50/* Whack an item; the item is an image_id in disguise, so we'll call
 51 * unload_add_on() for it.
 52 */
 53static void beos_nuke_dyn( PyObject *item )
 54{
 55	status_t retval;
 56
 57	if( item ) {
 58		image_id id = (image_id)PyInt_AsLong( item );
 59		
 60		retval = unload_add_on( id );
 61	}
 62}
 63
 64/* atexit() handler that'll call unload_add_on() for every item in the
 65 * dictionary.
 66 */
 67static void beos_cleanup_dyn( void )
 68{
 69	if( beos_dyn_images ) {
 70		int idx;
 71		int list_size;
 72		PyObject *id_list;
 73
 74#ifdef WITH_THREAD
 75		PyThread_acquire_lock( beos_dyn_lock, 1 );
 76#endif
 77
 78		id_list = PyDict_Values( beos_dyn_images );
 79
 80		list_size = PyList_Size( id_list );
 81		for( idx = 0; idx < list_size; idx++ ) {
 82			PyObject *the_item;
 83			
 84			the_item = PyList_GetItem( id_list, idx );
 85			beos_nuke_dyn( the_item );
 86		}
 87
 88		PyDict_Clear( beos_dyn_images );
 89
 90#ifdef WITH_THREAD
 91		PyThread_free_lock( beos_dyn_lock );
 92#endif
 93	}
 94}
 95
 96/*
 97 * Initialize our dictionary, and the dictionary mutex.
 98 */
 99static void beos_init_dyn( void )
100{
101	/* We're protected from a race condition here by the atomic init_count
102	 * variable.
103	 */
104	static int32 init_count = 0;
105	int32 val;
106
107	val = atomic_add( &init_count, 1 );
108	if( beos_dyn_images == NULL && val == 0 ) {
109		beos_dyn_images = PyDict_New();
110#ifdef WITH_THREAD
111		beos_dyn_lock = PyThread_allocate_lock();
112#endif
113		atexit( beos_cleanup_dyn );
114	}
115}
116
117/*
118 * Add an image_id to the dictionary; the module name of the loaded image
119 * is the key.  Note that if the key is already in the dict, we unload
120 * that image; this should allow reload() to work on dynamically loaded
121 * modules (super-keen!).
122 */
123static void beos_add_dyn( char *name, image_id id )
124{
125	int retval;
126	PyObject *py_id;
127
128	if( beos_dyn_images == NULL ) {
129		beos_init_dyn();
130	}
131
132#ifdef WITH_THREAD
133	retval = PyThread_acquire_lock( beos_dyn_lock, 1 );
134#endif
135
136	/* If there's already an object with this key in the dictionary,
137	 * we're doing a reload(), so let's nuke it.
138	 */
139	py_id = PyDict_GetItemString( beos_dyn_images, name );
140	if( py_id ) {
141		beos_nuke_dyn( py_id );
142		retval = PyDict_DelItemString( beos_dyn_images, name );
143	}
144
145	py_id = PyInt_FromLong( (long)id );
146	if( py_id ) {
147		retval = PyDict_SetItemString( beos_dyn_images, name, py_id );
148	}
149
150#ifdef WITH_THREAD
151	PyThread_release_lock( beos_dyn_lock );
152#endif
153}
154
155
156
157dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
158				    const char *pathname, FILE *fp)
159{
160	dl_funcptr p;
161	image_id the_id;
162	status_t retval;
163	char fullpath[PATH_MAX];
164	char funcname[258];
165
166	if( Py_VerboseFlag ) {
167		printf( "load_add_on( %s )\n", pathname );
168	}
169
170	/* Hmm, this old bug appears to have regenerated itself; if the
171	 * path isn't absolute, load_add_on() will fail.  Reported to Be
172	 * April 21, 1998.
173	 */
174	if( pathname[0] != '/' ) {
175		(void)getcwd( fullpath, PATH_MAX );
176		(void)strncat( fullpath, "/", PATH_MAX );
177		(void)strncat( fullpath, pathname, PATH_MAX );
178			
179		if( Py_VerboseFlag ) {
180			printf( "load_add_on( %s )\n", fullpath );
181		}
182	} else {
183		(void)strcpy( fullpath, pathname );
184	}
185
186	the_id = load_add_on( fullpath );
187	if( the_id < B_NO_ERROR ) {
188		/* It's too bad load_add_on() doesn't set errno or something...
189		 */
190		char buff[256];  /* hate hard-coded string sizes... */
191
192		if( Py_VerboseFlag ) {
193			printf( "load_add_on( %s ) failed", fullpath );
194		}
195
196		if( the_id == B_ERROR )
197			PyOS_snprintf( buff, sizeof(buff),
198				       "BeOS: Failed to load %.200s",
199				       fullpath );
200		else
201			PyOS_snprintf( buff, sizeof(buff), 
202				       "Unknown error loading %.200s", 
203				       fullpath );
204
205		PyErr_SetString( PyExc_ImportError, buff );
206		return NULL;
207	}
208
209	PyOS_snprintf(funcname, sizeof(funcname), "init%.200s", shortname);
210	if( Py_VerboseFlag ) {
211		printf( "get_image_symbol( %s )\n", funcname );
212	}
213
214	retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p );
215	if( retval != B_NO_ERROR || p == NULL ) {
216		/* That's bad, we can't find that symbol in the module...
217		 */
218		char buff[256];  /* hate hard-coded string sizes... */
219
220		if( Py_VerboseFlag ) {
221			printf( "get_image_symbol( %s ) failed", funcname );
222		}
223
224		switch( retval ) {
225		case B_BAD_IMAGE_ID:
226			PyOS_snprintf( buff, sizeof(buff),
227			       "can't load init function for dynamic module: "
228		               "Invalid image ID for %.180s", fullpath );
229			break;
230		case B_BAD_INDEX:
231			PyOS_snprintf( buff, sizeof(buff),
232			       "can't load init function for dynamic module: "
233		               "Bad index for %.180s", funcname );
234			break;
235		default:
236			PyOS_snprintf( buff, sizeof(buff),
237			       "can't load init function for dynamic module: "
238		               "Unknown error looking up %.180s", funcname );
239			break;
240		}
241
242		retval = unload_add_on( the_id );
243
244		PyErr_SetString( PyExc_ImportError, buff );
245		return NULL;
246	}
247
248	/* Save the module name and image ID for later so we can clean up
249	 * gracefully.
250	 */
251	beos_add_dyn( fqname, the_id );
252
253	return p;
254}