diff options
author | Ramiro Polla <ramiro.polla@gmail.com> | 2007-06-29 23:42:51 +0000 |
---|---|---|
committer | Ramiro Polla <ramiro.polla@gmail.com> | 2007-06-29 23:42:51 +0000 |
commit | 66a5baf77798bbf9dbfe1d7ddf6c591843d831c7 (patch) | |
tree | e9717c0daf0b316d139c5a2a535c1d6f9880f701 | |
parent | 40f1a4cc1e80c496aaab4f76a88810273ee0b15f (diff) | |
download | dlfcn-win32-66a5baf77798bbf9dbfe1d7ddf6c591843d831c7.tar.gz dlfcn-win32-66a5baf77798bbf9dbfe1d7ddf6c591843d831c7.tar.bz2 dlfcn-win32-66a5baf77798bbf9dbfe1d7ddf6c591843d831c7.zip |
Use double linked list instead of static array of 255 global objects.
-rw-r--r-- | dlfcn.c | 103 |
1 files changed, 68 insertions, 35 deletions
@@ -27,43 +27,76 @@ | |||
27 | * any kind of thread safety. | 27 | * any kind of thread safety. |
28 | */ | 28 | */ |
29 | 29 | ||
30 | /* I have no special reason to have set MAX_GLOBAL_OBJECTS to this value. Any | 30 | typedef struct global_object { |
31 | * comments are welcome. | 31 | HMODULE hModule; |
32 | */ | 32 | struct global_object *previous; |
33 | #define MAX_OBJECTS 255 | 33 | struct global_object *next; |
34 | } global_object; | ||
34 | 35 | ||
35 | static HMODULE global_objects[MAX_OBJECTS]; | 36 | static global_object first_object; |
36 | 37 | ||
37 | /* This function adds an object to the list of global objects. | 38 | /* These functions implement a double linked list for the global objects. */ |
38 | * The implementation is very simple and slow. | 39 | static global_object *global_search( HMODULE hModule ) |
39 | * TODO: should failing this function be enough to fail the call to dlopen( )? | ||
40 | */ | ||
41 | static void global_object_add( HMODULE hModule ) | ||
42 | { | 40 | { |
43 | int i; | 41 | global_object *pobject; |
44 | 42 | ||
45 | for( i = 0 ; i < MAX_OBJECTS ; i++ ) | 43 | if( hModule == NULL ) |
46 | { | 44 | return NULL; |
47 | if( !global_objects[i] ) | 45 | |
48 | { | 46 | for( pobject = &first_object; pobject ; pobject = pobject->next ) |
49 | global_objects[i] = hModule; | 47 | if( pobject->hModule == hModule ) |
50 | break; | 48 | return pobject; |
51 | } | 49 | |
52 | } | 50 | return NULL; |
53 | } | 51 | } |
54 | 52 | ||
55 | static void global_object_rem( HMODULE hModule ) | 53 | static void global_add( HMODULE hModule ) |
56 | { | 54 | { |
57 | int i; | 55 | global_object *pobject; |
56 | global_object *nobject; | ||
58 | 57 | ||
59 | for( i = 0 ; i < MAX_OBJECTS ; i++ ) | 58 | if( hModule == NULL ) |
60 | { | 59 | return; |
61 | if( global_objects[i] == hModule ) | 60 | |
62 | { | 61 | pobject = global_search( hModule ); |
63 | global_objects[i] = 0; | 62 | |
64 | break; | 63 | /* Do not add object again if it's already on the list */ |
65 | } | 64 | if( pobject ) |
66 | } | 65 | return; |
66 | |||
67 | for( pobject = &first_object; pobject->next ; pobject = pobject->next ); | ||
68 | |||
69 | nobject = malloc( sizeof(global_object) ); | ||
70 | |||
71 | /* Should this be enough to fail global_add, and therefore also fail | ||
72 | * dlopen? | ||
73 | */ | ||
74 | if( !nobject ) | ||
75 | return; | ||
76 | |||
77 | pobject->next = nobject; | ||
78 | nobject->previous = pobject; | ||
79 | nobject->hModule = hModule; | ||
80 | } | ||
81 | |||
82 | static void global_rem( HMODULE hModule ) | ||
83 | { | ||
84 | global_object *pobject; | ||
85 | |||
86 | if( hModule == NULL ) | ||
87 | return; | ||
88 | |||
89 | pobject = global_search( hModule ); | ||
90 | |||
91 | if( !pobject ) | ||
92 | return; | ||
93 | |||
94 | if( pobject->next ) | ||
95 | pobject->next->previous = pobject->previous; | ||
96 | if( pobject->previous ) | ||
97 | pobject->previous->next = pobject->next; | ||
98 | |||
99 | free( pobject ); | ||
67 | } | 100 | } |
68 | 101 | ||
69 | /* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one | 102 | /* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one |
@@ -191,7 +224,7 @@ void *dlopen( const char *file, int mode ) | |||
191 | if( !hModule ) | 224 | if( !hModule ) |
192 | save_err_str( lpFileName ); | 225 | save_err_str( lpFileName ); |
193 | else if( (mode & RTLD_GLOBAL) ) | 226 | else if( (mode & RTLD_GLOBAL) ) |
194 | global_object_add( hModule ); | 227 | global_add( hModule ); |
195 | } | 228 | } |
196 | 229 | ||
197 | /* Return to previous state of the error-mode bit flags. */ | 230 | /* Return to previous state of the error-mode bit flags. */ |
@@ -213,7 +246,7 @@ int dlclose( void *handle ) | |||
213 | * objects. | 246 | * objects. |
214 | */ | 247 | */ |
215 | if( ret ) | 248 | if( ret ) |
216 | global_object_rem( hModule ); | 249 | global_rem( hModule ); |
217 | else | 250 | else |
218 | save_err_ptr( handle ); | 251 | save_err_ptr( handle ); |
219 | 252 | ||
@@ -243,13 +276,13 @@ void *dlsym( void *handle, const char *name ) | |||
243 | 276 | ||
244 | if( hModule == handle ) | 277 | if( hModule == handle ) |
245 | { | 278 | { |
246 | int i; | 279 | global_object *pobject; |
247 | 280 | ||
248 | for( i = 0 ; i < MAX_OBJECTS ; i++ ) | 281 | for( pobject = &first_object; pobject ; pobject = pobject->next ) |
249 | { | 282 | { |
250 | if( global_objects[i] != 0 ) | 283 | if( pobject->hModule ) |
251 | { | 284 | { |
252 | symbol = GetProcAddress( global_objects[i], name ); | 285 | symbol = GetProcAddress( pobject->hModule, name ); |
253 | if( symbol != NULL ) | 286 | if( symbol != NULL ) |
254 | break; | 287 | break; |
255 | } | 288 | } |