[patch][commit] Blockable Component Enhancement

Dave Brolley <[email protected]>
Newsgroups gmane.comp.emulators.sid.devel
Message-ID <[email protected]>
Hi,

I've committed this patch which allows the blockable? attribute of a 
blocking component to be changed safely by other components using the 
SID component API. The actual setting of the internal state is delayed 
until the parent thread has (re)gained control.

Dave
blocking.sources.ChangeLog (text/plain, 662 B)
2005-08-02  Dave Brolley  <[email protected]>

	* sidbusutil.h (bus_arbitrator): Remove passthrough_pin.
	(check_passthrough): Now takes 'upstream' argument. Correct all calls.
	Don't check passthrough_pin here.
	(access_latency): New virtual method of bus_arbitrator.
	* sidblockingutil.h (blocking_component): Initialize still_blockable
	and control_status. Add blockable? using add_attribute_notify.
	(wait_for_child_thread): Assert that control_status != ctl_child_start.
	Return control_status.
	(child_completed): Set blockable to still_blockable.
	(set_blockable): New method of blocking_component.
	(still_blockable): New member of blocking_component.
blocking.sources.patch.txt (text/plain, 6.5 KB)
Index: sid/include/sidblockingutil.h
===================================================================
RCS file: /cvs/src/src/sid/include/sidblockingutil.h,v
retrieving revision 1.1
diff -c -p -r1.1 sidblockingutil.h
*** sid/include/sidblockingutil.h	10 May 2005 15:48:22 -0000	1.1
--- sid/include/sidblockingutil.h	2 Aug 2005 18:19:15 -0000
***************
*** 1,6 ****
  // sidblockingutil.h - Elements used for blockable components.  -*- C++ -*-
  
! // Copyright (C) 2004 Red Hat.
  // This file is part of SID and is licensed under the GPL.
  // See the file COPYING.SID for conditions for redistribution.
  
--- 1,6 ----
  // sidblockingutil.h - Elements used for blockable components.  -*- C++ -*-
  
! // 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.
  
*************** namespace sidutil
*** 28,44 ****
        self (child_self),
        child_created (false),
        child_thread_function (f),
!       blockable (false)
        {
  	add_attribute ("name", &name);
! 	add_attribute ("blockable?", & blockable, "setting");
        }
      ~blocking_component () throw()
        {
        }
  
    protected:
!     // Called by the parent thread to ensure that a child thread exists
      //
      void need_child_thread ()
        {
--- 28,77 ----
        self (child_self),
        child_created (false),
        child_thread_function (f),
!       blockable (false),
!       still_blockable (false),
!       control_status (ctl_parent)
        {
  	add_attribute ("name", &name);
! 	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:
!     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 ()
        {
*************** namespace sidutil
*** 81,113 ****
  	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);
  	control_status = ctl_child_start;
  	pthread_cond_signal (& child_resume_condition);
  
--- 114,125 ----
  	return wait_for_child_thread ();
        }
  
      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_child_start);
  	control_status = ctl_child_start;
  	pthread_cond_signal (& child_resume_condition);
  
*************** namespace sidutil
*** 121,144 ****
  	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;
        }
  
    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 ()
--- 133,143 ----
  	pthread_mutex_lock (& child_resume_mutex);
  
  	// Check the value of control_status
! 	assert (control_status != ctl_child_start);
! 	return control_status;
        }
  
    public:
      // Called by the child thread to signal normal completion of the child task
      //
      void child_completed ()
*************** namespace sidutil
*** 146,151 ****
--- 145,151 ----
  	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 ();
        }
  	    
*************** namespace sidutil
*** 159,165 ****
  	child_wait_for_resume ();
        }
  
!   private:
      // Called by the child thread to wait for a signal from the parent thread
      // to resume
      void child_wait_for_resume ()
--- 159,165 ----
  	child_wait_for_resume ();
        }
  
!   protected:	    
      // Called by the child thread to wait for a signal from the parent thread
      // to resume
      void child_wait_for_resume ()
*************** namespace sidutil
*** 182,190 ****
--- 182,199 ----
  	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;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.