Subversion Repositories HelenOS

Rev

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

Rev Author Line No. Line
2309 hudecek 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>
2400 hudecek 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
 
2309 hudecek 46
bool gquiet;
2400 hudecek 47
volatile bool finished;
48
typedef struct data_struc {
49
    int number;
50
    struct data_struc* next;
51
} data_t;
2309 hudecek 52
 
2400 hudecek 53
data_t* first;
54
SPINLOCK_INITIALIZE(write_lock);
55
 
56
 
57
 
58
static void reader(void* a)
2309 hudecek 59
{
2400 hudecek 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;
2309 hudecek 79
}
2400 hudecek 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
 
2309 hudecek 151
char * test_rcu1(bool quiet)
152
{
153
    gquiet = quiet;
2400 hudecek 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);
2309 hudecek 185
    return NULL;
186
 
187
}
188
 
189