Subversion Repositories HelenOS

Rev

Rev 2330 | Rev 2430 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2007 Jan Hudecek
  3.  * Copyright (c) 2005 Jakub Jermar
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. #include <synch/rcu.h>
  31. #include <print.h>
  32. #include <test.h>
  33. #include <arch/types.h>
  34. #include <proc/tasklet.h>
  35. #include <arch/barrier.h>
  36. #include <arch.h>
  37. #include <preemption.h>
  38. #include <proc/thread.h>
  39.  
  40.  
  41. #define RCU_MAX_I 1000
  42. #define READER_THREADS 10
  43. #define WRITER_THREADS 10
  44. #define THREADS_SLEEP_LENGTH (uint32_t)50
  45.  
  46. bool gquiet;
  47. volatile bool finished;
  48. typedef struct data_struc {
  49.     int number;
  50.     struct data_struc* next;
  51. } data_t;
  52.  
  53. data_t* first;
  54. SPINLOCK_INITIALIZE(write_lock);
  55.  
  56.  
  57.  
  58. static void reader(void* a)
  59. {
  60.     a = (a);
  61.     data_t* cur;
  62.     int i = 0;
  63.     while (true)
  64.     {
  65.         i = 0;
  66.         rcu_read_lock();
  67.         for (cur = rcu_dereference_pointer(first).next; cur != first; cur = cur->next) {
  68.             i += rcu_dereference_pointer(cur).number;
  69.         }
  70.         rcu_read_unlock();
  71.         thread_usleep(THREADS_SLEEP_LENGTH);
  72.         if (i>RCU_MAX_I || finished)
  73.         {
  74.             printf("@");
  75.             break;
  76.         }
  77.     }
  78.     finished = true;
  79. }
  80.  
  81. static void writer(void* a)
  82. {
  83.     a = (a);
  84.     data_t* cur;
  85.     data_t* newdata, *oldata;
  86.     rcu_callback_list_t* rcudata;
  87.     int i = 0;
  88.     printf("a1 ");
  89.     rcudata = malloc(sizeof(rcu_callback_list_t),0);
  90.     while (true)
  91.     {
  92.         i = rcu_dereference_pointer(first).number;
  93.         rcu_read_lock();
  94.         printf("a2 ");
  95.         for (cur = rcu_dereference_pointer(first).next; cur != first; cur = rcu_dereference_pointer(cur).next) {
  96.             i += rcu_dereference_pointer(cur).number;
  97.         }
  98.         rcu_read_unlock();
  99.         if (!gquiet)
  100.             printf("i%d ",i);
  101.         if (i>RCU_MAX_I || finished)
  102.         {
  103.             printf("!");
  104.             break;
  105.         }
  106.         printf("a2b ");
  107.         thread_usleep(THREADS_SLEEP_LENGTH);
  108.  
  109.         printf("a3 ");
  110.         newdata = malloc(sizeof(data_t),0);
  111.         printf("a4 ");
  112.         rcu_read_lock();
  113.         //prepend a new member
  114.         spinlock_lock(&write_lock);
  115.         printf("a5 ");
  116.         newdata->number = (i/10)+1;
  117.         oldata = first;
  118.         newdata->next = first;
  119.         rcu_assign_pointer(first, newdata);
  120.         printf("a6 ");
  121.         rcu_sync_callback(&rcu_callback_free, oldata, rcudata);
  122.         spinlock_unlock(&write_lock);
  123.         printf("a7 ");
  124.         rcu_read_unlock();
  125.         thread_usleep(THREADS_SLEEP_LENGTH);
  126.         printf("a8 ");
  127.         if (!gquiet)
  128.             printf(".",i);
  129.  
  130.         rcu_read_lock();
  131.         for (cur = rcu_dereference_pointer(first).next; rcu_dereference_pointer(cur).number % 5 != 4 && cur != first; cur = rcu_dereference_pointer(cur).next) {
  132.         }
  133.         if (cur != first){
  134.             //delete the cur->next
  135.             spinlock_lock(&write_lock);
  136.             oldata = rcu_dereference_pointer(cur).next;
  137.             newdata->next = rcu_dereference_pointer(rcu_dereference_pointer(cur).next).next;
  138.             rcu_assign_pointer(rcu_dereference_pointer(cur).next, newdata);
  139.             rcu_sync_callback(&rcu_callback_free, oldata, rcudata);
  140.             spinlock_unlock(&write_lock);
  141.             if (!gquiet)
  142.                 printf(", ",i);
  143.  
  144.         }
  145.         rcu_read_unlock();
  146.         thread_usleep(THREADS_SLEEP_LENGTH);
  147.     }
  148.     finished = true;
  149. }
  150.  
  151. char * test_rcu1(bool quiet)
  152. {
  153.     gquiet = quiet;
  154.     data_t* cur, *oldata;
  155.     int i;
  156.     thread_t* t;
  157.     thread_t** threads;
  158.     first = malloc(sizeof(data_t),0);
  159.     first->number = 10;
  160.     first->next = first;
  161.     threads = malloc(sizeof(thread_t*),0);
  162.     finished = false;
  163.  
  164.     for(i = 0; i< WRITER_THREADS; i++) {
  165.         threads[i]=t=thread_create(writer,NULL, TASK, 0, "writerthread", false );
  166.         if (t != NULL)
  167.             thread_ready(t);
  168.     }
  169.  
  170.     for(i = 0; i< READER_THREADS; i++) {
  171.         threads[WRITER_THREADS+i]=t=thread_create(reader,NULL, TASK, 0, "readerthread", false );
  172.         if (t != NULL)
  173.             thread_ready(t);
  174.     }
  175.  
  176.     for (i=0;i<WRITER_THREADS+READER_THREADS;i++)
  177.         thread_join(threads[i]);
  178.  
  179.     for(cur=first->next;cur->next!=first;) {
  180.         oldata = cur->next;
  181.         free(cur);
  182.         cur = oldata;
  183.     }
  184.     free(first);
  185.     return NULL;
  186.  
  187. }
  188.  
  189.  
  190.