Re: [PATCH, TEST] Make functions in random.c thread safe
Hi. Me and Roman are curious about zero comments on this. We'll try to improve the diff if it is not ok. Just let us know. Anyone? :) On Wed, Oct 3, 2012 at 4:06 PM, Alexey Suslikov alexey.susli...@gmail.com wrote: Hi. Is there any progress/comments on this? On Fri, Sep 28, 2012 at 11:29 PM, Alexey Suslikov alexey.susli...@gmail.com wrote: Hi. With input from tedu@, guenther@ and others, below are: 1) test case; 2) backtrace for test case; 3) locking diff; 4) dmesg (amd64 GENERIC.MP built from 2012-09-28 CVS). Diff introduces no changes to srandomdev(): correct me if I'm wrong, but no mutex can be used since sysctl can sleep. Rebuild and reinstall in src/lib/librthread and src/lib/libc after applying the diff. Expect test case (and Kannel port of course) not crashing after rebuild and reinstall. Cheers, Alexey 1) test case. #include pthread.h #include stdio.h #include stdlib.h #include assert.h #include unistd.h #define NUM_THREADS1800 void *TaskCode(void *argument) { struct timeval tv; gettimeofday(tv, 0); srandom((getpid() 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); return NULL; } int main(void) { pthread_t threads[NUM_THREADS]; int thread_args[NUM_THREADS]; int rc, i; /* create all threads */ for (i=0; iNUM_THREADS; ++i) { thread_args[i] = i; rc = pthread_create(threads[i], NULL, TaskCode, (void *) thread_args[i]); assert(0 == rc); } /* wait for all threads to complete */ for (i=0; iNUM_THREADS; ++i) { rc = pthread_join(threads[i], NULL); assert(0 == rc); } printf(Test srandom success\n); exit(EXIT_SUCCESS); } 2) backtrace for test case. Program received signal SIGSEGV, Segmentation fault. [Switching to thread 1030380] 0x19d34d618f8e in random () at /usr/src/lib/libc/stdlib/random.c:387 387 *fptr += *rptr; (gdb) bt #0 0x19d34d618f8e in random () at /usr/src/lib/libc/stdlib/random.c:387 #1 0x19d34d619169 in srandom (x=Variable x is not available. ) at /usr/src/lib/libc/stdlib/random.c:216 #2 0x19d14fe1 in TaskCode (argument=0x7f7ea004) at test_srandom.c:14 #3 0x19d34999d11e in _rthread_start (v=Variable v is not available. ) at /usr/src/lib/librthread/rthread.c:122 #4 0x19d34d5f0f9b in __tfork_thread () at /usr/src/lib/libc/arch/amd64/sys/tfork_thread.S:75 Cannot access memory at address 0x19d344efb000 3) locking diff. Index: lib/libc/include/thread_private.h === RCS file: /cvs/src/lib/libc/include/thread_private.h,v retrieving revision 1.25 diff -u -p -r1.25 thread_private.h --- lib/libc/include/thread_private.h 16 Oct 2011 06:29:56 - 1.25 +++ lib/libc/include/thread_private.h 27 Sep 2012 10:48:45 - @@ -172,4 +172,16 @@ void _thread_arc4_unlock(void); _thread_arc4_unlock();\ } while (0) +void _thread_random_lock(void); +void _thread_random_unlock(void); + +#define _RANDOM_LOCK() do {\ + if (__isthreaded) \ + _thread_random_lock(); \ + } while (0) +#define _RANDOM_UNLOCK() do {\ + if (__isthreaded) \ + _thread_random_unlock();\ + } while (0) + #endif /* _THREAD_PRIVATE_H_ */ Index: lib/libc/stdlib/random.c === RCS file: /cvs/src/lib/libc/stdlib/random.c,v retrieving revision 1.17 diff -u -p -r1.17 random.c --- lib/libc/stdlib/random.c1 Jun 2012 01:01:57 - 1.17 +++ lib/libc/stdlib/random.c27 Sep 2012 10:48:45 - @@ -35,6 +35,10 @@ #include stdio.h #include stdlib.h #include unistd.h +#include thread_private.h + +static void srandom_unlocked(unsigned int); +static long random_unlocked(void); /* * random.c: @@ -186,8 +190,8 @@ static int rand_sep = SEP_3; * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] * for default usage relies on values produced by this routine. */ -void -srandom(unsigned int x) +static void +srandom_unlocked(unsigned int x) { int i; int32_t test; @@ -213,10 +217,18 @@ srandom(unsigned int x) fptr = state[rand_sep]; rptr = state[0]; for (i = 0; i 10 * rand_deg; i++) - (void)random(); + (void)random_unlocked(); } } +void
Re: [PATCH, TEST] Make functions in random.c thread safe
Hi. Is there any progress/comments on this? On Fri, Sep 28, 2012 at 11:29 PM, Alexey Suslikov alexey.susli...@gmail.com wrote: Hi. With input from tedu@, guenther@ and others, below are: 1) test case; 2) backtrace for test case; 3) locking diff; 4) dmesg (amd64 GENERIC.MP built from 2012-09-28 CVS). Diff introduces no changes to srandomdev(): correct me if I'm wrong, but no mutex can be used since sysctl can sleep. Rebuild and reinstall in src/lib/librthread and src/lib/libc after applying the diff. Expect test case (and Kannel port of course) not crashing after rebuild and reinstall. Cheers, Alexey 1) test case. #include pthread.h #include stdio.h #include stdlib.h #include assert.h #include unistd.h #define NUM_THREADS1800 void *TaskCode(void *argument) { struct timeval tv; gettimeofday(tv, 0); srandom((getpid() 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); return NULL; } int main(void) { pthread_t threads[NUM_THREADS]; int thread_args[NUM_THREADS]; int rc, i; /* create all threads */ for (i=0; iNUM_THREADS; ++i) { thread_args[i] = i; rc = pthread_create(threads[i], NULL, TaskCode, (void *) thread_args[i]); assert(0 == rc); } /* wait for all threads to complete */ for (i=0; iNUM_THREADS; ++i) { rc = pthread_join(threads[i], NULL); assert(0 == rc); } printf(Test srandom success\n); exit(EXIT_SUCCESS); } 2) backtrace for test case. Program received signal SIGSEGV, Segmentation fault. [Switching to thread 1030380] 0x19d34d618f8e in random () at /usr/src/lib/libc/stdlib/random.c:387 387 *fptr += *rptr; (gdb) bt #0 0x19d34d618f8e in random () at /usr/src/lib/libc/stdlib/random.c:387 #1 0x19d34d619169 in srandom (x=Variable x is not available. ) at /usr/src/lib/libc/stdlib/random.c:216 #2 0x19d14fe1 in TaskCode (argument=0x7f7ea004) at test_srandom.c:14 #3 0x19d34999d11e in _rthread_start (v=Variable v is not available. ) at /usr/src/lib/librthread/rthread.c:122 #4 0x19d34d5f0f9b in __tfork_thread () at /usr/src/lib/libc/arch/amd64/sys/tfork_thread.S:75 Cannot access memory at address 0x19d344efb000 3) locking diff. Index: lib/libc/include/thread_private.h === RCS file: /cvs/src/lib/libc/include/thread_private.h,v retrieving revision 1.25 diff -u -p -r1.25 thread_private.h --- lib/libc/include/thread_private.h 16 Oct 2011 06:29:56 - 1.25 +++ lib/libc/include/thread_private.h 27 Sep 2012 10:48:45 - @@ -172,4 +172,16 @@ void _thread_arc4_unlock(void); _thread_arc4_unlock();\ } while (0) +void _thread_random_lock(void); +void _thread_random_unlock(void); + +#define _RANDOM_LOCK() do {\ + if (__isthreaded) \ + _thread_random_lock(); \ + } while (0) +#define _RANDOM_UNLOCK() do {\ + if (__isthreaded) \ + _thread_random_unlock();\ + } while (0) + #endif /* _THREAD_PRIVATE_H_ */ Index: lib/libc/stdlib/random.c === RCS file: /cvs/src/lib/libc/stdlib/random.c,v retrieving revision 1.17 diff -u -p -r1.17 random.c --- lib/libc/stdlib/random.c1 Jun 2012 01:01:57 - 1.17 +++ lib/libc/stdlib/random.c27 Sep 2012 10:48:45 - @@ -35,6 +35,10 @@ #include stdio.h #include stdlib.h #include unistd.h +#include thread_private.h + +static void srandom_unlocked(unsigned int); +static long random_unlocked(void); /* * random.c: @@ -186,8 +190,8 @@ static int rand_sep = SEP_3; * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] * for default usage relies on values produced by this routine. */ -void -srandom(unsigned int x) +static void +srandom_unlocked(unsigned int x) { int i; int32_t test; @@ -213,10 +217,18 @@ srandom(unsigned int x) fptr = state[rand_sep]; rptr = state[0]; for (i = 0; i 10 * rand_deg; i++) - (void)random(); + (void)random_unlocked(); } } +void +srandom(unsigned int x) +{ + _RANDOM_LOCK(); + srandom_unlocked(x); + _RANDOM_UNLOCK(); +} + /* * srandomdev: * @@ -273,12 +285,15 @@ initstate(u_int seed, char *arg_state, s { char *ostate
[PATCH, TEST] Make functions in random.c thread safe
Hi. With input from tedu@, guenther@ and others, below are: 1) test case; 2) backtrace for test case; 3) locking diff; 4) dmesg (amd64 GENERIC.MP built from 2012-09-28 CVS). Diff introduces no changes to srandomdev(): correct me if I'm wrong, but no mutex can be used since sysctl can sleep. Rebuild and reinstall in src/lib/librthread and src/lib/libc after applying the diff. Expect test case (and Kannel port of course) not crashing after rebuild and reinstall. Cheers, Alexey 1) test case. #include pthread.h #include stdio.h #include stdlib.h #include assert.h #include unistd.h #define NUM_THREADS1800 void *TaskCode(void *argument) { struct timeval tv; gettimeofday(tv, 0); srandom((getpid() 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); return NULL; } int main(void) { pthread_t threads[NUM_THREADS]; int thread_args[NUM_THREADS]; int rc, i; /* create all threads */ for (i=0; iNUM_THREADS; ++i) { thread_args[i] = i; rc = pthread_create(threads[i], NULL, TaskCode, (void *) thread_args[i]); assert(0 == rc); } /* wait for all threads to complete */ for (i=0; iNUM_THREADS; ++i) { rc = pthread_join(threads[i], NULL); assert(0 == rc); } printf(Test srandom success\n); exit(EXIT_SUCCESS); } 2) backtrace for test case. Program received signal SIGSEGV, Segmentation fault. [Switching to thread 1030380] 0x19d34d618f8e in random () at /usr/src/lib/libc/stdlib/random.c:387 387 *fptr += *rptr; (gdb) bt #0 0x19d34d618f8e in random () at /usr/src/lib/libc/stdlib/random.c:387 #1 0x19d34d619169 in srandom (x=Variable x is not available. ) at /usr/src/lib/libc/stdlib/random.c:216 #2 0x19d14fe1 in TaskCode (argument=0x7f7ea004) at test_srandom.c:14 #3 0x19d34999d11e in _rthread_start (v=Variable v is not available. ) at /usr/src/lib/librthread/rthread.c:122 #4 0x19d34d5f0f9b in __tfork_thread () at /usr/src/lib/libc/arch/amd64/sys/tfork_thread.S:75 Cannot access memory at address 0x19d344efb000 3) locking diff. Index: lib/libc/include/thread_private.h === RCS file: /cvs/src/lib/libc/include/thread_private.h,v retrieving revision 1.25 diff -u -p -r1.25 thread_private.h --- lib/libc/include/thread_private.h 16 Oct 2011 06:29:56 - 1.25 +++ lib/libc/include/thread_private.h 27 Sep 2012 10:48:45 - @@ -172,4 +172,16 @@ void _thread_arc4_unlock(void); _thread_arc4_unlock();\ } while (0) +void _thread_random_lock(void); +void _thread_random_unlock(void); + +#define _RANDOM_LOCK() do {\ + if (__isthreaded) \ + _thread_random_lock(); \ + } while (0) +#define _RANDOM_UNLOCK() do {\ + if (__isthreaded) \ + _thread_random_unlock();\ + } while (0) + #endif /* _THREAD_PRIVATE_H_ */ Index: lib/libc/stdlib/random.c === RCS file: /cvs/src/lib/libc/stdlib/random.c,v retrieving revision 1.17 diff -u -p -r1.17 random.c --- lib/libc/stdlib/random.c1 Jun 2012 01:01:57 - 1.17 +++ lib/libc/stdlib/random.c27 Sep 2012 10:48:45 - @@ -35,6 +35,10 @@ #include stdio.h #include stdlib.h #include unistd.h +#include thread_private.h + +static void srandom_unlocked(unsigned int); +static long random_unlocked(void); /* * random.c: @@ -186,8 +190,8 @@ static int rand_sep = SEP_3; * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] * for default usage relies on values produced by this routine. */ -void -srandom(unsigned int x) +static void +srandom_unlocked(unsigned int x) { int i; int32_t test; @@ -213,10 +217,18 @@ srandom(unsigned int x) fptr = state[rand_sep]; rptr = state[0]; for (i = 0; i 10 * rand_deg; i++) - (void)random(); + (void)random_unlocked(); } } +void +srandom(unsigned int x) +{ + _RANDOM_LOCK(); + srandom_unlocked(x); + _RANDOM_UNLOCK(); +} + /* * srandomdev: * @@ -273,12 +285,15 @@ initstate(u_int seed, char *arg_state, s { char *ostate = (char *)(state[-1]); + _RANDOM_LOCK(); if (rand_type == TYPE_0) state[-1] = rand_type; else state[-1] = MAX_TYPES * (rptr - state) + rand_type; - if (n BREAK_0) + if (n BREAK_0) { +