gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r2212 - GNUnet/src/util


From: durner
Subject: [GNUnet-SVN] r2212 - GNUnet/src/util
Date: Wed, 26 Oct 2005 12:14:54 -0700 (PDT)

Author: durner
Date: 2005-10-26 12:14:49 -0700 (Wed, 26 Oct 2005)
New Revision: 2212

Modified:
   GNUnet/src/util/semaphore.c
Log:
Work around gprof's inability to profile multi-threaded apps

Modified: GNUnet/src/util/semaphore.c
===================================================================
--- GNUnet/src/util/semaphore.c 2005-10-25 19:53:29 UTC (rev 2211)
+++ GNUnet/src/util/semaphore.c 2005-10-26 19:14:49 UTC (rev 2212)
@@ -51,6 +51,10 @@
  */
 #define USE_CHECKING_MUTEX 1
 
+/**
+ * Enable gprof workaround for multi-threaded apps
+ */
+#define ENABLE_PROFILER 0
 
 typedef struct {
 #if SOLARIS || FREEBSD5 || OSX
@@ -89,6 +93,43 @@
 #ifndef _MSC_VER
 extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *attr, int kind);
 #endif
+
+#if ENABLE_PROFILER
+/**
+ * @brief Passed to wrapper_routine by PTHREAD_CREATE
+ */
+typedef struct wrapper_s {
+  void *(*start_routine) (void *);
+  void *arg;
+
+  pthread_mutex_t lock;
+  pthread_cond_t wait;
+
+  struct itimerval itimer;
+
+} wrapper_t;
+
+/**
+ * @brief Workaround for gprof, see comment in PTHREAD_CREATE()
+ */
+static void *wrapper_routine(void *data) {
+  /* Put user data in thread-local variables */
+  void *(*start_routine) (void *) = ((wrapper_t *) data)->start_routine;
+  void *arg = ((wrapper_t *) data)->arg;
+
+  /* Set the profile timer value */
+  setitimer(ITIMER_PROF, &((wrapper_t *) data)->itimer, NULL);
+
+  /* Tell the calling thread that we don't need its data anymore */
+  pthread_mutex_lock(&((wrapper_t *) data)->lock);
+  pthread_cond_signal(&((wrapper_t *) data)->wait);
+  pthread_mutex_unlock(&((wrapper_t *) data)->lock);
+
+  /* Call the real function */
+  return start_routine(arg);
+}
+#endif
+
 /* ********************* public methods ******************* */
 
 void create_mutex_(Mutex * mutex) {
@@ -361,7 +402,24 @@
   pthread_t * handle;
   pthread_attr_t stack_size_custom_attr;
   int ret;
+#if ENABLE_PROFILER
+  wrapper_t wrapper_data;
+  int i_return;
 
+  /* This works around gprof's inability to profile multi-threaded
+     applications (based on 
http://sam.zoy.org/writings/programming/gprof.html).
+     It uses a wrapper for the thread's real main function to set
+     the thread's itimer value to the main thread's itimer value. */
+
+  /* Initialize the wrapper structure */
+  wrapper_data.start_routine = main;
+  wrapper_data.arg = arg;
+  getitimer(ITIMER_PROF, &wrapper_data.itimer);
+  pthread_cond_init(&wrapper_data.wait, NULL);
+  pthread_mutex_init(&wrapper_data.lock, NULL);
+  pthread_mutex_lock(&wrapper_data.lock);
+#endif
+
   handle = MALLOC(sizeof(pthread_t));
 #ifdef MINGW
   memset(handle, 0, sizeof(pthread_t));
@@ -372,8 +430,23 @@
                            stackSize);
   ret = pthread_create(handle,
                       &stack_size_custom_attr,
+#if !ENABLE_PROFILER
                       main,
-                      arg);                    
+                      arg);
+#else
+           &wrapper_routine,
+           &wrapper_data);
+  
+  /* If the thread was successfully spawned, wait for the data
+     to be released */
+  if(ret == 0)
+    pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
+
+  pthread_mutex_unlock(&wrapper_data.lock);
+  pthread_mutex_destroy(&wrapper_data.lock);
+  pthread_cond_destroy(&wrapper_data.wait);
+#endif
+
   if (ret != 0) {
     FREE(handle);
     pt->internal = NULL;





reply via email to

[Prev in Thread] Current Thread [Next in Thread]