// sidblockingutil.h - Elements used for blockable components. -*- C++ -*-
-// Copyright (C) 2004 Red Hat.
+// Copyright (C) 2004, 2005 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
self (child_self),
child_created (false),
child_thread_function (f),
- blockable (false)
+ blockable (false),
+ still_blockable (false),
+ control_status (ctl_parent)
{
add_attribute ("name", &name);
- add_attribute ("blockable?", & blockable, "setting");
+ add_attribute_notify ("blockable?", & still_blockable, this,
+ & blocking_component::set_blockable,
+ "setting");
}
~blocking_component () throw()
{
}
+ // -------------------------------------------------------------------
+ // Child thread management
+ //
+ public:
+ void child_init ()
+ {
+ log (10, "%s: child_init\n", name.c_str ());
+ assert (child_created);
+ // Lock both mutexes
+ pthread_mutex_lock (& child_resume_mutex);
+ pthread_mutex_lock (& child_stopped_mutex);
+ }
+
protected:
- // Called by the parent thread to ensure that a child thread exists
+ void parent_init ()
+ {
+ log (10, "%s: parent_init\n", name.c_str ());
+
+ // Create mutexes for synchronizing the parent and child threads
+ pthread_mutex_init (& child_resume_mutex, NULL);
+ pthread_cond_init (& child_resume_condition, NULL);
+ pthread_mutex_init (& child_stopped_mutex, NULL);
+ pthread_cond_init (& child_stopped_condition, NULL);
+
+ // Lock both mutexes
+ pthread_mutex_lock (& child_resume_mutex);
+ pthread_mutex_lock (& child_stopped_mutex);
+ control_status = ctl_parent;
+ }
+
+ // Called to ensure that a child thread exists
//
void need_child_thread ()
{
return wait_for_child_thread ();
}
- private:
- // Called once by the parent thread just before the child thread is
- // created.
- void parent_init ()
- {
- log (10, "%s: parent_init\n", name.c_str ());
-
- // Create mutexes for synchronizing the parent and child threads
- pthread_mutex_init (& child_resume_mutex, NULL);
- pthread_cond_init (& child_resume_condition, NULL);
- pthread_mutex_init (& child_stopped_mutex, NULL);
- pthread_cond_init (& child_stopped_condition, NULL);
-
- // Lock both mutexes
- pthread_mutex_lock (& child_resume_mutex);
- pthread_mutex_lock (& child_stopped_mutex);
- control_status = ctl_parent;
- }
-
- // Called by the parent to wait for the child thread to give up control
- //
int wait_for_child_thread ()
{
log (10, "%s: wait_for_child_thread\n", name.c_str ());
// Signal the child to resume
- assert (control_status == ctl_parent);
+ assert (control_status != ctl_child_start);
control_status = ctl_child_start;
pthread_cond_signal (& child_resume_condition);
pthread_mutex_lock (& child_resume_mutex);
// Check the value of control_status
- int s = control_status;
- assert (s != ctl_child_start);
- control_status = ctl_parent;
- return s;
+ assert (control_status != ctl_child_start);
+ return control_status;
}
public:
- // Called by the child thread once when it is created.
- //
- void child_init ()
- {
- log (10, "%s: child_init\n", name.c_str ());
- assert (child_created);
- // Lock both mutexes
- pthread_mutex_lock (& child_resume_mutex);
- pthread_mutex_lock (& child_stopped_mutex);
- }
-
// Called by the child thread to signal normal completion of the child task
//
void child_completed ()
log (10, "%s: child_completed\n", name.c_str ());
log (11, "%s: child sending completion signal\n", name.c_str ());
control_status = ctl_child_complete;
+ blockable = still_blockable;
child_wait_for_resume ();
}
child_wait_for_resume ();
}
- private:
+ protected:
// Called by the child thread to wait for a signal from the parent thread
// to resume
void child_wait_for_resume ()
assert (control_status == ctl_child_start);
}
+ void set_blockable ()
+ {
+ // Never change the status of 'blockable' while the child thread is
+ // active.
+ if (control_status == ctl_parent || control_status == ctl_child_complete)
+ blockable = still_blockable;
+ }
+
protected:
string name;
bool blockable;
+ bool still_blockable;
void *self;
bool child_created;
pthread_t child_thread;
// sidbusutil.h -*- C++ -*- Different types and sizes of buses.
-// Copyright (C) 1999, 2000, 2001, 2002, 2004 Red Hat.
+// Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Red Hat.
// This file is part of SID and is licensed under the GPL.
// See the file COPYING.SID for conditions for redistribution.
running_pin.set_active_high ();
add_pin ("active", & active_pin);
active_pin.set_active_high ();
- add_pin ("passthrough", & passthrough_pin);
- passthrough_pin.set_active_high ();
}
~bus_arbitrator () throw () { }
sid::bus::status
write(int upstream, sid::host_int_4 addr, DataType data)
{
- if (ulog_level >= 8 || ! check_passthrough ())
+ if (ulog_level >= 8 || ! check_passthrough (upstream))
log (5, "%s: received write request from %s interface at 0x%x\n",
name.c_str (), up2str(upstream), addr);
return arbitrate_write (upstream, downstream_for_address (addr), addr, data);
sid::bus::status
read(int upstream, sid::host_int_4 addr, DataType& data)
{
- if (ulog_level >= 8 || ! check_passthrough ())
+ if (ulog_level >= 8 || ! check_passthrough (upstream))
log (5, "%s: received read request from %s interface at 0x%x\n",
name.c_str (), up2str(upstream), addr);
return arbitrate_read (upstream, downstream_for_address (addr), addr, data);
DataType& data)
{
// Check for direct passthrough
- if (check_passthrough ())
+ if (check_passthrough (upstream))
return downstream_bus (downstream)->read (addr, data);
// Prioritize the request
DataType data)
{
// Check for direct passthrough
- if (check_passthrough ())
+ if (check_passthrough (upstream))
return downstream_bus (downstream)->write(addr, data);
// Prioritize the request
return s;
}
- bool check_passthrough ()
+ virtual bool check_passthrough (int = 0)
{
- if (passthrough_pin.state () == binary_pin_active)
- {
- log (8, "%s: passthrough enabled\n", name.c_str ());
- return true;
- }
-
if (running_pin.state () != binary_pin_active
|| active_pin.state () != binary_pin_active)
{
log (8, "%s: system is idle -- passthrough\n", name.c_str ());
return true;
}
- return false;
- }
+ return false;
+ }
+
+ protected:
+ // Methods for timing
+ //
+ // Default to no latency
+ virtual sid::host_int_2 access_latency (bus_request &r) { return 0; }
protected:
// Route locking
//
binary_input_pin running_pin;
binary_input_pin active_pin;
- binary_input_pin passthrough_pin;
};
}