tags:

views:

53

answers:

2

I have a program that I link with many libraries. I run my application on profiler and found out that most of the time is spent in "waiting" state after some network requests. Those requests are effect of my code calling sleeping_function() from external library. I call this function in a loop which executes many, many times so all waiting times sum up to huge amounts.

As I cannot modify the sleeping_function() I want to start a few threads to run a few iterations of my loop in parallel. The problem is that this function internally uses some global variables.

Is there a way to tell linker on SunOS that I want to link specific libraries in a way that will place all variables from them in Thread Local Storage?

A: 

I don’t think you’ll be able to achieve this with just the linker, but you might be able to get something working with some code in C.

The problem is that a call to load a library that is already loaded will return a reference to the already loaded instance instead of loading a new copy. A quick look at the documentation for dlopen and LoadLibrary seems to confirm that there’s no way to load the same library more than once, at least not if you want the image to be prepared for execution. One way to circumvent this would be to prevent the OS from knowing that it is the same library. To do this you could make a copy of the file.

Some pseudo code, just replace calls to sleeping_function with calls to call_sleeping_function_thread_safe:

char *shared_lib_name

void sleeping_function_thread_init(char *lib_name);

void call_sleeping_function_thread_safe()
{
  void *lib_handle;
  pthread_t pthread;
  new_file_name = make_copy_of_file(shared_lib_name);

  pthread_create(&pthread, NULL, sleeping_function_thread_init, new_file_name);
}

void sleeping_function_thread_init(char *lib_name)
{
  void *lib_handle;
  void (*)() sleeping_function;

  lib_handle = dlopen(lib_name, RTLD_LOCAL);
  sleeping_function = dlsym(lib_handle, "sleeping_function")
  while (...)
    sleeping_function;
  dlclose(lib_handle);
  delete_file(lib_name);      
}

For windows dlopen becomes LoadLibrary and dlsym becomes GetProcAddress etc... but the basic idea would still work.

torak
It won't work since I have to link the whole program statically.
elmo
+1  A: 

In general, this is a bad idea. Global data isn't the only issue that may prevent a non thread-safe library from running in a multithreaded environment.

As one example, what if the library had a global variable that points to a memory-mapped file that it always maps into a single, hardcoded address. In this case, with your technique, you would have one global variable per thread, but they would all point to the same memory location, which would be trashed by multi-threaded access.

John Saunders
I agree, but this is not the case. I have access to the sources of the library, but I cannot change anything and have to link against the given static library object.
elmo
That was one example. Are you sure that the library makes no assumptions that it is running in a single thread? Not even implicit assumptions?
John Saunders