42,7 → 42,7 |
#include <proc/thread.h> |
|
//number of nodes in the list. The sum of the list will grow up to RCU_MAX_I^2 |
#define RCU_MAX_I 500 |
#define RCU_MAX_I 5000 |
//number of reader and writer threads in the test |
#define READER_THREADS 10 |
#define WRITER_THREADS 10 |
69,8 → 69,7 |
a = (a); |
data_t* cur; |
int i = 0; |
while (true) |
{ |
while (true) { |
//entering read critical section |
rcu_read_lock(); |
//proper dereferencing |
79,14 → 78,17 |
i += cur->number; |
} |
rcu_read_unlock(); |
if (i>RCU_MAX_I*RCU_MAX_I || cfinished>0) |
{ |
printf("@"); |
if (i>RCU_MAX_I*RCU_MAX_I || cfinished>0) { |
if (!gquiet) |
printf("@"); |
break; |
} |
thread_usleep(THREADS_SLEEP_LENGTH); |
} |
//we must achieve some kind of synchronization gcc wont emit inc [cfinished] |
spinlock_lock(&write_lock); |
cfinished++; |
spinlock_unlock(&write_lock); |
} |
|
static void writer(void* a) |
97,8 → 99,7 |
data_t* oldata; |
rcu_callback_list_t* rcudata; |
int i = 0; |
while (true) |
{ |
while (true) { |
//we must allocate the rcu structure each time, because it gets freed after the callback |
//we allocate it outside any critical section, as it could block |
rcudata = malloc(sizeof(rcu_callback_list_t),0); |
108,11 → 109,11 |
i += cur->number; |
} |
rcu_read_unlock(); |
if (!gquiet) |
if (!gquiet && false) |
printf("i%d ",i); |
if (i>RCU_MAX_I*RCU_MAX_I || cfinished>0) |
{ |
printf("!"); |
if (i>RCU_MAX_I*RCU_MAX_I || cfinished>0) { |
if (!gquiet) |
printf("!"); |
break; |
} |
|
119,20 → 120,17 |
//insert a new member |
newdata = malloc(sizeof(data_t),0); |
newdata->number = (i/(RCU_MAX_I/2))+1; |
rcu_read_lock(); |
//we have to acquire the lock for writing to the structure |
spinlock_lock(&write_lock); |
newdata->next = first; |
//rcu_assign_pointer takes care of the necessary write barriers |
rcu_assign_pointer(first, newdata); |
if (!gquiet) |
if (!gquiet && false) |
printf("prepending:%x,n:%d ", newdata, newdata->number); |
spinlock_unlock(&write_lock); |
rcu_read_unlock(); |
|
|
//replace a random member |
rcu_read_lock(); |
//we have to lock the spinlock now, because we'll use the cur pointer later |
//RCU doesn't provide guarantee that cur->next will point to a member of the list |
//note that read critical section DOES guarantee that the *cur will be allocated space |
144,10 → 142,10 |
if (cur->next != NULL) { |
newdata = malloc(sizeof(data_t),0); |
//the change of number member could be done atomically, its here just to simulate some real work |
newdata->number = (i/(RCU_MAX_I/2))+5; |
newdata->number = (i/(RCU_MAX_I/2))+10; |
newdata->next = cur->next->next; |
oldata = cur->next; |
if (!gquiet) |
if (!gquiet && false) |
printf("free:%x,n:%d ", cur->next, cur->next->number); |
rcu_assign_pointer(cur->next, newdata); |
//free the old member when it is safe (i.e. no references are held) |
154,9 → 152,11 |
rcu_sync_callback(&rcu_callback_free, oldata, rcudata); |
spinlock_unlock(&write_lock); |
} |
rcu_read_unlock(); |
} |
//we must achieve some kind of synchronization gcc wont emit inc [cfinished] |
spinlock_lock(&write_lock); |
cfinished++; |
spinlock_unlock(&write_lock); |
} |
|
char * test_rcu1(bool quiet) |
195,7 → 195,8 |
} |
//wait for completion |
while (cfinished<WRITER_THREADS+READER_THREADS); |
printf("\nfinished all threads!\n"); |
if (!gquiet) |
printf("\nfinished all threads!\n"); |
//free the list |
for(cur=first->next;cur!=NULL;) { |
oldata = cur->next; |