summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/SystemTap_Tapset_Reference/tapsets.tmpl7
-rw-r--r--runtime/arith.c24
-rw-r--r--tapset/random.stp14
-rw-r--r--testsuite/systemtap.base/rand.exp3
-rw-r--r--testsuite/systemtap.base/rand.stp19
5 files changed, 59 insertions, 8 deletions
diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl
index fcfb1e85..99f72727 100644
--- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl
+++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl
@@ -214,4 +214,11 @@
</para>
!Itapset/logging.stp
</chapter>
+ <chapter id="random.stp">
+ <title>Random functions Tapset</title>
+ <para>
+ These functions deal with random number generation.
+ </para>
+!Itapset/random.stp
+ </chapter>
</book>
diff --git a/runtime/arith.c b/runtime/arith.c
index d1d0da29..4c818a76 100644
--- a/runtime/arith.c
+++ b/runtime/arith.c
@@ -84,26 +84,34 @@ static int64_t _stp_mod64 (const char **error, int64_t x, int64_t y)
}
-#ifndef _STP_TEST_
-/** Return a random integer between -n and n.
+/** Return a random integer between 0 and n - 1.
* @param n how far from zero to go. Make it positive but less than a million or so.
*/
-static int _stp_random_pm (int n)
+static unsigned long _stp_random_u (unsigned long n)
{
static unsigned long seed;
static int initialized_p = 0;
-
+
if (unlikely (! initialized_p)) {
seed = (unsigned long) jiffies;
initialized_p = 1;
}
-
+
/* from glibc rand man page */
seed = seed * 1103515245 + 12345;
-
- return (seed % (2*n+1)-n);
+
+ return (n == 0 ? 0 : seed % n);
}
-#endif /* _STP_TEST_ */
+
+
+/** Return a random integer between -n and n.
+ * @param n how far from zero to go. Make it positive but less than a million or so.
+ */
+static int _stp_random_pm (unsigned n)
+{
+ return -(int)n + (int)_stp_random_u (2*n + 1);
+}
+
#if defined (__i386__) || defined (__arm__)
diff --git a/tapset/random.stp b/tapset/random.stp
new file mode 100644
index 00000000..9b2fdc70
--- /dev/null
+++ b/tapset/random.stp
@@ -0,0 +1,14 @@
+/**
+ * sfunction randint - Return a random number between [0,n)
+ * @n: Number past upper limit of range, not larger than 2**20.
+ */
+function randint:long(n:long)
+%{ /* unprivileged */
+#define RANDMAX (1024*1024)
+ if (THIS->n > RANDMAX)
+ CONTEXT->last_error = "range too wide";
+ else {
+ THIS->__retvalue = (uint64_t) _stp_random_u((unsigned long) THIS->n);
+ }
+#undef RANDMAX
+%}
diff --git a/testsuite/systemtap.base/rand.exp b/testsuite/systemtap.base/rand.exp
new file mode 100644
index 00000000..9b372e18
--- /dev/null
+++ b/testsuite/systemtap.base/rand.exp
@@ -0,0 +1,3 @@
+set test "rand"
+set ::result_string {PASS}
+stap_run2 $srcdir/$subdir/$test.stp
diff --git a/testsuite/systemtap.base/rand.stp b/testsuite/systemtap.base/rand.stp
new file mode 100644
index 00000000..d584e5f7
--- /dev/null
+++ b/testsuite/systemtap.base/rand.stp
@@ -0,0 +1,19 @@
+function checkStatus(status:long){
+ if (status == 1){
+ printf("%s\n","FAIL")
+ }else{
+ printf("%s\n","PASS")
+ }
+}
+
+probe begin
+{
+ status = 0
+ for (i=1; i <= 100; i++){
+ if (randint(i) < 0 || randint(i) > i) {
+ status = 1
+ }
+ }
+ checkStatus(status)
+ exit()
+}