/*
* Copyright (c) 2007 Jan Hudecek
* Copyright (c) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/** @addtogroup sync
* @{
*/
/** @file
*/
#include <synch/rcu.h>
#include <synch/waitq.h>
#include <arch.h>
#include <config.h>
#include <arch/types.h>
#include <ddi/tasklet.h>
#include <synch/spinlock.h>
#include <time/delay.h>
#include <panic.h>
#include <print.h>
typedef struct rcu_global
{
uint32_t current_batch;
uint32_t completed_batch;
bool next_batch_waiting;
} rcu_global_t;
typedef struct rcu_callback_list
{
struct rcu_callback_list* next;
void (*func)(void*);
void* data;
bool* cpu_mask;
} rcu_callback_list_t;
typedef struct rcu_percpu
{
uint32_t current_batch_number;
uint32_t QS_passed;
bool QS_pending;
rcu_callback_list_t* next_batch, *current_batch, *done_batch;
} rcu_percpu_t;
rcu_global_t _rcu_global;
rcu_percpu_t* _rcu_cpu_lists;
void rcu_init(void)
{
_rcu_cpu_lists
= malloc(sizeof(rcu_percpu_t
)*config.
cpu_count,0);
_rcu_global.completed_batch = -1;
_rcu_global.current_batch = -1;
_rcu_global.next_batch_waiting = -1;
}
void rcu_synchronize(void)
{
waitq_t wq;
waitq_initialize(&wq);
rcu_sync_callback(rcu_synchronize_callback_function, &wq);
waitq_sleep(&wq);
}
void rcu_synchronize_callback_function(void* waitq)
{
waitq_wakeup(((waitq_t*)waitq), true);
}
void rcu_sync_callback(void (*func)(void* data), void* data)
{
int i;
rcu_callback_list_t *rd;
rd
= malloc(sizeof(rcu_desc
), 0);
rd->func = func;
rd->data = data;
rd->next = NULL;
rd
->cpu_mask
= malloc (sizeof(bool
)*config.
cpu_count,0);
for (i=0;i<config.cpu_count;i++)
rd->cpu_mask[i]=false;
i = ++(_rcu_global.current_batch);
_rcu_global.next_batch_waiting = true;
rd->next = _rcu_cpu_lists[0].next_batch;
for (i=0;i<config.cpu_count;i++)
{
_rcu_cpu_lists[i].next_batch = rd;
_rcu_cpu_lists[i].QS_pending = true;
}
//TODO:tasklet, after_thread_ran, polishing
}