Use chopstx
[gnuk/neug.git] / src / random.c
index e426da5..f2d6075 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * random.c - random number generation
  *
- * Copyright (C) 2011, 2012 Free Software Initiative of Japan
+ * Copyright (C) 2011, 2012, 2013 Free Software Initiative of Japan
  * Author: NIIBE Yutaka <gniibe@fsij.org>
  *
  * This file is a part of NeuG, a True Random Number Generator
  *
  */
 
-#include <string.h>            /* for memcpy */
+#include <stdint.h>
+#include <string.h>
+#include <chopstx.h>
+
 #include "config.h"
 
-#include "ch.h"
-#include "hal.h"
 #include "sys.h"
 #include "neug.h"
+#include "stm32f103.h"
 #include "adc.h"
 #include "sha256.h"
 
-Thread *rng_thread;
-#define ADC_DATA_AVAILABLE ((eventmask_t)1)
+chopstx_mutex_t adc_mtx;
+chopstx_cond_t adc_cond;
+int adc_waiting;
+int adc_data_available;
 
 static uint32_t adc_buf[SHA256_BLOCK_SIZE/sizeof (uint32_t)];
 
@@ -95,7 +99,8 @@ static void ep_fill_initial_string (void)
 
 static void ep_init (int mode)
 {
-  chEvtClearFlags (ADC_DATA_AVAILABLE);
+  adc_data_available = 0;
+
   if (mode == NEUG_MODE_RAW)
     {
       ep_round = EP_ROUND_RAW;
@@ -356,9 +361,9 @@ static void noise_source_continuous_test (uint8_t noise)
  */
 struct rng_rb {
   uint32_t *buf;
-  Mutex m;
-  CondVar data_available;
-  CondVar space_available;
+  chopstx_mutex_t m;
+  chopstx_cond_t data_available;
+  chopstx_cond_t space_available;
   uint8_t head, tail;
   uint8_t size;
   unsigned int full :1;
@@ -369,9 +374,9 @@ static void rb_init (struct rng_rb *rb, uint32_t *p, uint8_t size)
 {
   rb->buf = p;
   rb->size = size;
-  chMtxInit (&rb->m);
-  chCondInit (&rb->data_available);
-  chCondInit (&rb->space_available);
+  chopstx_mutex_init (&rb->m);
+  chopstx_cond_init (&rb->data_available);
+  chopstx_cond_init (&rb->space_available);
   rb->head = rb->tail = 0;
   rb->full = 0;
   rb->empty = 1;
@@ -401,27 +406,41 @@ static uint32_t rb_del (struct rng_rb *rb)
 }
 
 uint8_t neug_mode;
+static int rng_should_terminate;
+static chopstx_t rng_thread;
+
 
 /**
  * @brief Random number generation thread.
  */
-static msg_t rng (void *arg)
+static void *
+rng (void *arg)
 {
   struct rng_rb *rb = (struct rng_rb *)arg;
 
-  rng_thread = chThdSelf ();
+  rng_should_terminate = 0;
+  chopstx_mutex_init (&adc_mtx);
+  chopstx_cond_init (&adc_cond);
 
   /* Enable ADCs */
   adc_start ();
 
   ep_init (NEUG_MODE_CONDITIONED);
 
-  while (!chThdShouldTerminate ())
+  while (!rng_should_terminate)
     {
       int n;
       int mode = neug_mode;
 
-      chEvtWaitOne (ADC_DATA_AVAILABLE); /* Get ADC sampling.  */
+      chopstx_mutex_lock (&adc_mtx);
+      if (!adc_data_available)
+       {
+         adc_waiting = 1;
+         chopstx_cond_wait (&adc_cond, &adc_mtx);
+         adc_waiting = 0;
+       }
+      adc_data_available = 0;
+      chopstx_mutex_unlock (&adc_mtx);
 
       if ((n = ep_process (mode)))
        {
@@ -438,9 +457,9 @@ static msg_t rng (void *arg)
 
          vp = ep_output (mode);
 
-         chMtxLock (&rb->m);
+         chopstx_mutex_lock (&rb->m);
          while (rb->full)
-           chCondWait (&rb->space_available);
+           chopstx_cond_wait (&rb->space_available, &rb->m);
 
          for (i = 0; i < n; i++)
            {
@@ -449,18 +468,22 @@ static msg_t rng (void *arg)
                break;
            }
 
-         chCondSignal (&rb->data_available);
-         chMtxUnlock ();
+         chopstx_cond_signal (&rb->data_available);
+         chopstx_mutex_unlock (&rb->m);
        }
     }
 
   adc_stop ();
 
-  return 0;
+  return NULL;
 }
 
 static struct rng_rb the_ring_buffer;
-static WORKING_AREA(wa_rng, 256);
+
+extern uint8_t __process2_stack_base__, __process2_stack_size__;
+const uint32_t __stackaddr_rng = (uint32_t)&__process2_stack_base__;
+const size_t __stacksize_rng = (size_t)&__process2_stack_size__;
+#define PRIO_RNG 3
 
 /**
  * @brief Initialize NeuG.
@@ -468,6 +491,7 @@ static WORKING_AREA(wa_rng, 256);
 void
 neug_init (uint32_t *buf, uint8_t size)
 {
+  chopstx_attr_t attr;
   const uint32_t *u = (const uint32_t *)unique_device_id ();
   struct rng_rb *rb = &the_ring_buffer;
   int i;
@@ -484,7 +508,11 @@ neug_init (uint32_t *buf, uint8_t size)
 
   neug_mode = NEUG_MODE_CONDITIONED;
   rb_init (rb, buf, size);
-  chThdCreateStatic (wa_rng, sizeof (wa_rng), NORMALPRIO, rng, rb);
+
+  chopstx_attr_init (&attr);
+  chopstx_attr_setschedparam (&attr, PRIO_RNG);
+  chopstx_attr_setstack (&attr, __stackaddr_rng, __stacksize_rng);
+  chopstx_create (&rng_thread, &attr, rng, rb);
 }
 
 /**
@@ -495,11 +523,11 @@ neug_flush (void)
 {
   struct rng_rb *rb = &the_ring_buffer;
 
-  chMtxLock (&rb->m);
+  chopstx_mutex_lock (&rb->m);
   while (!rb->empty)
     (void)rb_del (rb);
-  chCondSignal (&rb->space_available);
-  chMtxUnlock ();
+  chopstx_cond_signal (&rb->space_available);
+  chopstx_mutex_unlock (&rb->m);
 }
 
 
@@ -511,10 +539,10 @@ neug_kick_filling (void)
 {
   struct rng_rb *rb = &the_ring_buffer;
 
-  chMtxLock (&rb->m);
+  chopstx_mutex_lock (&rb->m);
   if (!rb->full)
-    chCondSignal (&rb->space_available);
-  chMtxUnlock ();
+    chopstx_cond_signal (&rb->space_available);
+  chopstx_mutex_unlock (&rb->m);
 }
 
 /**
@@ -529,13 +557,13 @@ neug_get (int kick)
   struct rng_rb *rb = &the_ring_buffer;
   uint32_t v;
 
-  chMtxLock (&rb->m);
+  chopstx_mutex_lock (&rb->m);
   while (rb->empty)
-    chCondWait (&rb->data_available);
+    chopstx_cond_wait (&rb->data_available, &rb->m);
   v = rb_del (rb);
   if (kick)
-    chCondSignal (&rb->space_available);
-  chMtxUnlock ();
+    chopstx_cond_signal (&rb->space_available);
+  chopstx_mutex_unlock (&rb->m);
 
   return v;
 }
@@ -546,15 +574,15 @@ neug_get_nonblock (uint32_t *p)
   struct rng_rb *rb = &the_ring_buffer;
   int r = 0;
 
-  chMtxLock (&rb->m);
+  chopstx_mutex_lock (&rb->m);
   if (rb->empty)
     {
       r = -1;
-      chCondSignal (&rb->space_available);
+      chopstx_cond_signal (&rb->space_available);
     }
   else
     *p = rb_del (rb);
-  chMtxUnlock ();
+  chopstx_mutex_unlock (&rb->m);
 
   return r;
 }
@@ -564,7 +592,7 @@ int neug_consume_random (void (*proc) (uint32_t, int))
   int i = 0;
   struct rng_rb *rb = &the_ring_buffer;
 
-  chMtxLock (&rb->m);
+  chopstx_mutex_lock (&rb->m);
   while (!rb->empty)
     {
       uint32_t v;
@@ -573,8 +601,8 @@ int neug_consume_random (void (*proc) (uint32_t, int))
       proc (v, i);
       i++;
     }
-  chCondSignal (&rb->space_available);
-  chMtxUnlock ();
+  chopstx_cond_signal (&rb->space_available);
+  chopstx_mutex_unlock (&rb->m);
 
   return i;
 }
@@ -584,22 +612,20 @@ neug_wait_full (void)
 {
   struct rng_rb *rb = &the_ring_buffer;
 
-  chMtxLock (&rb->m);
+  chopstx_mutex_lock (&rb->m);
   while (!rb->full)
-    chCondWait (&rb->data_available);
-  chMtxUnlock ();
+    chopstx_cond_wait (&rb->data_available, &rb->m);
+  chopstx_mutex_unlock (&rb->m);
 }
 
 void
 neug_fini (void)
 {
-  if (rng_thread)
-    {
-      chThdTerminate (rng_thread);
-      neug_get (1);
-      chThdWait (rng_thread);
-      rng_thread = NULL;
-    }
+  rng_should_terminate = 1;
+  neug_get (1);
+#if 0
+  chopstx_join (rng_thread, NULL);
+#endif
 }
 
 void
@@ -610,8 +636,14 @@ neug_mode_select (uint8_t mode)
 
   neug_wait_full ();
 
-  while (rng_thread->p_state != THD_STATE_WTCOND)
-    chThdSleep (MS2ST (1));
+  chopstx_mutex_lock (&adc_mtx);
+  while (adc_waiting == 0)
+    {
+      chopstx_mutex_unlock (&adc_mtx);
+      chopstx_usleep (1000);
+      chopstx_mutex_lock (&adc_mtx);
+    }
+  chopstx_mutex_unlock (&adc_mtx);
 
   ep_init (mode);
   noise_source_cnt_max_reset ();