genrand_unix problem on Solaris



Hi,

I'm not subscribed to this list, so please, CC: me on any replies. Thx.

I've found a serious problem with genrand_unix on Solaris.

It took ages for nautilus to start or to change to a different directory.
I found that it spends most of the time in genrand_unix (ORBit/src/orb/genrand.c),
so I had a closer look.

According to the Solaris man page of setitimer:

           In   the   current   and   previous   releases,   when
           setitimer(ITIMER_REAL,   ...)  is  called  in  a  mul-
           tithreaded  process  linked  with  -lthread   (Solaris
           threads)   or  -lpthread  (POSIX  threads;  see  stan-
           dards(5)), the resulting SIGALRM is sent to the  bound
           thread  that  called   setitimer();  setitimer() has a
           per-thread semantic when called from a  bound  thread.

           Also, calling this routine from an unbound  thread  is
           not  guaranteed  to  work  as  in  the  case  of bound
           threads. The resulting SIGALRM may  be  sent  to  some
           other  thread  (see  alarm(2)). This is a bug and will
           not be fixed since the per-thread semantic is going to
           be discontinued.

           Hence, for multithreaded (Solaris or  POSIX)  programs
           in  the current  and previous releases, the only reli-
           able way to use the ITIMER_REAL flag  is  to  call  it
           from a bound thread which does not mask SIGALRM and to
           expect the SIGALRM  to  be  delivered  to  this  bound
           thread.

           New MT applications should  not  use  this  flag,  and
           should use alarm(2) instead.

Since nautilus is an MT app, and it uses unbound threads
(in gnome-vfs/libgnomevfs-pthreads),
it looks like it didn't always get the ALARM signal and kept waiting
for a long-long time...

Of course you can't implement genrand_unix using alarm(), so
I wrote a new genrand function that uses lrand48() to generate
random numbers. Attached is my patch.
Using this patch nautilus started to work much-much faster.

Let me know if you have any other solutions to this problem.

Cheers,

Laca

Index: ORBit/configure.in
===================================================================
RCS file: /export/CVS/GNOME-RE/ORBit/configure.in,v
retrieving revision 1.98.4.10
diff -u -r1.98.4.10 configure.in
--- ORBit/configure.in	2001/01/18 20:16:42	1.98.4.10
+++ ORBit/configure.in	2001/02/16 11:40:03
@@ -133,7 +133,7 @@
 fi
 
 AC_SUBST(ORBIT_HAVE_ALLOCA_H)
-AC_CHECK_FUNCS(poll basename)
+AC_CHECK_FUNCS(poll basename lrand48)
 AC_CHECK_FUNC(socket,,[AC_CHECK_LIB(socket,socket)])
 AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
 
Index: ORBit/src/orb/genrand.c
===================================================================
RCS file: /export/CVS/GNOME-RE/ORBit/src/orb/genrand.c,v
retrieving revision 1.2.4.1
diff -u -r1.2.4.1 genrand.c
--- ORBit/src/orb/genrand.c	2001/01/18 20:16:44	1.2.4.1
+++ ORBit/src/orb/genrand.c	2001/02/16 11:40:03
@@ -1,3 +1,4 @@
+#include <config.h>
 #include "genrand.h"
 #include "ORBitutil/util.h"
 #include <unistd.h>
@@ -50,6 +51,24 @@
 }
 
 static gboolean
+genrand_lrand48(guchar *buffer, int buf_len)
+{
+#ifdef HAVE_LRAND48
+#ifndef LRAND48_MAX
+#define LRAND48_MAX 2147483648.0
+#endif
+  int i;
+  srand48(random());
+
+  for(i = 0; i < buf_len; i++)
+    buffer[i] = (guchar) (lrand48() / (LRAND48_MAX / 256));
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
+static gboolean
 genrand_unix(guchar *buffer, int buf_len)
 {
   struct sigaction sa, oldsa;
@@ -105,6 +124,8 @@
   g_return_if_fail(buf_len);
 
   if(genrand_dev(buffer, buf_len))
+    return;
+  else if(genrand_lrand48(buffer, buf_len))
     return;
   else if(genrand_unix(buffer, buf_len))
     return;


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