summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1995-12-01 21:08:03 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1995-12-01 21:08:03 +0000
commitcaaa47c29b1c6196e9b9cebd5ee0ebd069e46418 (patch)
tree7775b44616cab65442baadb4e713845bac9b7d1b
parentAdded support for new synchronization algorithm. Specifically, the routine (diff)
downloadrtems-caaa47c29b1c6196e9b9cebd5ee0ebd069e46418.tar.bz2
Added new synchronization algorithm.
-rw-r--r--c/src/exec/score/src/threadq.c150
-rw-r--r--cpukit/score/src/threadq.c150
2 files changed, 184 insertions, 116 deletions
diff --git a/c/src/exec/score/src/threadq.c b/c/src/exec/score/src/threadq.c
index ef38258d2b..87e7903df4 100644
--- a/c/src/exec/score/src/threadq.c
+++ b/c/src/exec/score/src/threadq.c
@@ -112,7 +112,7 @@ void _Thread_queue_Enqueue(
_Watchdog_Insert_ticks(
&the_thread->Timer,
timeout,
- WATCHDOG_NO_ACTIVATE
+ WATCHDOG_ACTIVATE_NOW
);
}
@@ -121,8 +121,7 @@ void _Thread_queue_Enqueue(
_Thread_queue_Enqueue_fifo( the_thread_queue, the_thread, timeout );
break;
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
- _Thread_queue_Enqueue_priority(
- the_thread_queue, the_thread, timeout );
+ _Thread_queue_Enqueue_priority( the_thread_queue, the_thread, timeout );
break;
}
}
@@ -150,7 +149,6 @@ Thread_Control *_Thread_queue_Dequeue(
)
{
Thread_Control *the_thread;
- ISR_Level level;
switch ( the_thread_queue->discipline ) {
case THREAD_QUEUE_DISCIPLINE_FIFO:
@@ -164,18 +162,7 @@ Thread_Control *_Thread_queue_Dequeue(
break;
}
- if ( !_Thread_Is_null( the_thread ) )
- return( the_thread );
-
- _ISR_Disable( level );
- if ( the_thread_queue->sync == FALSE ) {
- _ISR_Enable( level );
- return( NULL );
- }
-
- the_thread_queue->sync = FALSE;
- _ISR_Enable( level );
- return( _Thread_Executing );
+ return( the_thread );
}
/*PAGE
@@ -331,8 +318,9 @@ void _Thread_queue_Timeout(
void *ignored
)
{
- Thread_Control *the_thread;
- Objects_Locations location;
+ Thread_Control *the_thread;
+ Thread_queue_Control *the_thread_queue;
+ Objects_Locations location;
the_thread = _Thread_Get( id, &location );
switch ( location ) {
@@ -340,8 +328,15 @@ void _Thread_queue_Timeout(
case OBJECTS_REMOTE: /* impossible */
break;
case OBJECTS_LOCAL:
- the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
- _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+ the_thread_queue = the_thread->Wait.queue;
+
+ if ( the_thread_queue->sync == TRUE && _Thread_Is_executing(the_thread)) {
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
+ the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
+ } else {
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+ }
_Thread_Unnest_dispatch();
break;
}
@@ -374,30 +369,39 @@ void _Thread_queue_Enqueue_fifo (
ISR_Level level;
_ISR_Disable( level );
- if ( the_thread_queue->sync == TRUE ) {
- the_thread_queue->sync = FALSE;
- _Chain_Append_unprotected(
- &the_thread_queue->Queues.Fifo,
- &the_thread->Object.Node
- );
+ switch ( the_thread_queue->sync_state ) {
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ the_thread_queue->sync = FALSE;
+ _Chain_Append_unprotected(
+ &the_thread_queue->Queues.Fifo,
+ &the_thread->Object.Node
+ );
+ _ISR_Enable( level );
+ return;
- if ( timeout != WATCHDOG_NO_TIMEOUT )
- _Watchdog_Activate( &the_thread->Timer );
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _ISR_Enable( level );
+ break;
- _ISR_Enable( level );
- return;
+ case THREAD_QUEUE_SATISFIED:
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+ break;
}
- if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
- _ISR_Enable( level );
- _Thread_Unblock( the_thread );
- } else {
- _Watchdog_Deactivate( &the_thread->Timer );
- _ISR_Enable( level );
- (void) _Watchdog_Remove( &the_thread->Timer );
- _Thread_Unblock( the_thread );
- }
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
_Thread_MP_Free_proxy( the_thread );
@@ -447,10 +451,15 @@ Thread_Control *_Thread_queue_Dequeue_fifo(
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
_Thread_MP_Free_proxy( the_thread );
- return( the_thread );
+ return the_thread;
+ } else if ( the_thread_queue->sync ) {
+ the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
+ _ISR_Enable( level );
+ return _Thread_Executing;
+ } else {
+ _ISR_Enable( level );
+ return NULL;
}
- _ISR_Enable( level );
- return( NULL );
}
/*PAGE
@@ -597,12 +606,10 @@ restart_forward_search:
search_thread =
(Thread_Control *)search_thread->Object.Node.next;
}
- if ( the_thread_queue->sync == FALSE )
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
goto syncronize;
the_thread_queue->sync = FALSE;
- if ( timeout != WATCHDOG_NO_TIMEOUT )
- _Watchdog_Activate( &the_thread->Timer );
if ( priority == search_priority )
goto equal_priority;
@@ -643,12 +650,10 @@ restart_reverse_search:
search_thread = (Thread_Control *)
search_thread->Object.Node.previous;
}
- if ( !the_thread_queue->sync )
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
goto syncronize;
the_thread_queue->sync = FALSE;
- if ( timeout != WATCHDOG_NO_TIMEOUT )
- _Watchdog_Activate( &the_thread->Timer );
if ( priority == search_priority )
goto equal_priority;
@@ -677,15 +682,37 @@ equal_priority: /* add at end of priority group */
return;
syncronize:
- if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
- _ISR_Enable( level );
- _Thread_Unblock( the_thread );
- } else {
- _Watchdog_Deactivate( &the_thread->Timer );
- _ISR_Enable( level );
- (void) _Watchdog_Remove( &the_thread->Timer );
- _Thread_Unblock( the_thread );
+
+ switch ( the_thread_queue->sync_state ) {
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ /*
+ * All of this was dealt with above. This should never happen.
+ */
+ break;
+
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _ISR_Enable( level );
+ break;
+
+ case THREAD_QUEUE_SATISFIED:
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+ break;
}
+
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
+
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
_Thread_MP_Free_proxy( the_thread );
}
@@ -721,17 +748,24 @@ Thread_Control *_Thread_queue_Dequeue_priority(
Chain_Node *next_node;
Chain_Node *previous_node;
+ _ISR_Disable( level );
for( index=0 ;
index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
index++ ) {
- _ISR_Disable( level );
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
the_thread = (Thread_Control *)
the_thread_queue->Queues.Priority[ index ].first;
goto dequeue;
}
- _ISR_Enable( level );
}
+
+ if ( the_thread_queue->sync ) {
+ the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
+ _ISR_Enable( level );
+ return _Thread_Executing;
+ }
+
+ _ISR_Enable( level );
return NULL;
dequeue:
diff --git a/cpukit/score/src/threadq.c b/cpukit/score/src/threadq.c
index ef38258d2b..87e7903df4 100644
--- a/cpukit/score/src/threadq.c
+++ b/cpukit/score/src/threadq.c
@@ -112,7 +112,7 @@ void _Thread_queue_Enqueue(
_Watchdog_Insert_ticks(
&the_thread->Timer,
timeout,
- WATCHDOG_NO_ACTIVATE
+ WATCHDOG_ACTIVATE_NOW
);
}
@@ -121,8 +121,7 @@ void _Thread_queue_Enqueue(
_Thread_queue_Enqueue_fifo( the_thread_queue, the_thread, timeout );
break;
case THREAD_QUEUE_DISCIPLINE_PRIORITY:
- _Thread_queue_Enqueue_priority(
- the_thread_queue, the_thread, timeout );
+ _Thread_queue_Enqueue_priority( the_thread_queue, the_thread, timeout );
break;
}
}
@@ -150,7 +149,6 @@ Thread_Control *_Thread_queue_Dequeue(
)
{
Thread_Control *the_thread;
- ISR_Level level;
switch ( the_thread_queue->discipline ) {
case THREAD_QUEUE_DISCIPLINE_FIFO:
@@ -164,18 +162,7 @@ Thread_Control *_Thread_queue_Dequeue(
break;
}
- if ( !_Thread_Is_null( the_thread ) )
- return( the_thread );
-
- _ISR_Disable( level );
- if ( the_thread_queue->sync == FALSE ) {
- _ISR_Enable( level );
- return( NULL );
- }
-
- the_thread_queue->sync = FALSE;
- _ISR_Enable( level );
- return( _Thread_Executing );
+ return( the_thread );
}
/*PAGE
@@ -331,8 +318,9 @@ void _Thread_queue_Timeout(
void *ignored
)
{
- Thread_Control *the_thread;
- Objects_Locations location;
+ Thread_Control *the_thread;
+ Thread_queue_Control *the_thread_queue;
+ Objects_Locations location;
the_thread = _Thread_Get( id, &location );
switch ( location ) {
@@ -340,8 +328,15 @@ void _Thread_queue_Timeout(
case OBJECTS_REMOTE: /* impossible */
break;
case OBJECTS_LOCAL:
- the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
- _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+ the_thread_queue = the_thread->Wait.queue;
+
+ if ( the_thread_queue->sync == TRUE && _Thread_Is_executing(the_thread)) {
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
+ the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
+ } else {
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+ }
_Thread_Unnest_dispatch();
break;
}
@@ -374,30 +369,39 @@ void _Thread_queue_Enqueue_fifo (
ISR_Level level;
_ISR_Disable( level );
- if ( the_thread_queue->sync == TRUE ) {
- the_thread_queue->sync = FALSE;
- _Chain_Append_unprotected(
- &the_thread_queue->Queues.Fifo,
- &the_thread->Object.Node
- );
+ switch ( the_thread_queue->sync_state ) {
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ the_thread_queue->sync = FALSE;
+ _Chain_Append_unprotected(
+ &the_thread_queue->Queues.Fifo,
+ &the_thread->Object.Node
+ );
+ _ISR_Enable( level );
+ return;
- if ( timeout != WATCHDOG_NO_TIMEOUT )
- _Watchdog_Activate( &the_thread->Timer );
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _ISR_Enable( level );
+ break;
- _ISR_Enable( level );
- return;
+ case THREAD_QUEUE_SATISFIED:
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+ break;
}
- if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
- _ISR_Enable( level );
- _Thread_Unblock( the_thread );
- } else {
- _Watchdog_Deactivate( &the_thread->Timer );
- _ISR_Enable( level );
- (void) _Watchdog_Remove( &the_thread->Timer );
- _Thread_Unblock( the_thread );
- }
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
_Thread_MP_Free_proxy( the_thread );
@@ -447,10 +451,15 @@ Thread_Control *_Thread_queue_Dequeue_fifo(
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
_Thread_MP_Free_proxy( the_thread );
- return( the_thread );
+ return the_thread;
+ } else if ( the_thread_queue->sync ) {
+ the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
+ _ISR_Enable( level );
+ return _Thread_Executing;
+ } else {
+ _ISR_Enable( level );
+ return NULL;
}
- _ISR_Enable( level );
- return( NULL );
}
/*PAGE
@@ -597,12 +606,10 @@ restart_forward_search:
search_thread =
(Thread_Control *)search_thread->Object.Node.next;
}
- if ( the_thread_queue->sync == FALSE )
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
goto syncronize;
the_thread_queue->sync = FALSE;
- if ( timeout != WATCHDOG_NO_TIMEOUT )
- _Watchdog_Activate( &the_thread->Timer );
if ( priority == search_priority )
goto equal_priority;
@@ -643,12 +650,10 @@ restart_reverse_search:
search_thread = (Thread_Control *)
search_thread->Object.Node.previous;
}
- if ( !the_thread_queue->sync )
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
goto syncronize;
the_thread_queue->sync = FALSE;
- if ( timeout != WATCHDOG_NO_TIMEOUT )
- _Watchdog_Activate( &the_thread->Timer );
if ( priority == search_priority )
goto equal_priority;
@@ -677,15 +682,37 @@ equal_priority: /* add at end of priority group */
return;
syncronize:
- if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
- _ISR_Enable( level );
- _Thread_Unblock( the_thread );
- } else {
- _Watchdog_Deactivate( &the_thread->Timer );
- _ISR_Enable( level );
- (void) _Watchdog_Remove( &the_thread->Timer );
- _Thread_Unblock( the_thread );
+
+ switch ( the_thread_queue->sync_state ) {
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ /*
+ * All of this was dealt with above. This should never happen.
+ */
+ break;
+
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _ISR_Enable( level );
+ break;
+
+ case THREAD_QUEUE_SATISFIED:
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+ break;
}
+
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
+
if ( !_Objects_Is_local_id( the_thread->Object.id ) )
_Thread_MP_Free_proxy( the_thread );
}
@@ -721,17 +748,24 @@ Thread_Control *_Thread_queue_Dequeue_priority(
Chain_Node *next_node;
Chain_Node *previous_node;
+ _ISR_Disable( level );
for( index=0 ;
index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
index++ ) {
- _ISR_Disable( level );
if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
the_thread = (Thread_Control *)
the_thread_queue->Queues.Priority[ index ].first;
goto dequeue;
}
- _ISR_Enable( level );
}
+
+ if ( the_thread_queue->sync ) {
+ the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
+ _ISR_Enable( level );
+ return _Thread_Executing;
+ }
+
+ _ISR_Enable( level );
return NULL;
dequeue: