mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
Properly fix locking in the scheduler
Original commit message from CVS: Properly fix locking in the scheduler
This commit is contained in:
parent
641b5a1e5d
commit
0694a337a1
1 changed files with 37 additions and 29 deletions
|
@ -125,6 +125,10 @@ static void gst_basic_scheduler_show (GstScheduler *sched);
|
|||
|
||||
static GstSchedulerClass *parent_class = NULL;
|
||||
|
||||
/* for threaded bins, these pre- and post-run functions lock and unlock the
|
||||
* elements. we have to avoid deadlocks, so we make these convenience macros
|
||||
* that will avoid using do_cothread_switch from within the scheduler. */
|
||||
|
||||
#define do_element_switch(element) G_STMT_START{ \
|
||||
GstElement *from = SCHED (element)->current; \
|
||||
if (from->post_run_func) \
|
||||
|
@ -135,6 +139,23 @@ static GstSchedulerClass *parent_class = NULL;
|
|||
do_cothread_switch (GST_ELEMENT_THREADSTATE (element)); \
|
||||
}G_STMT_END
|
||||
|
||||
#define do_switch_to_main(sched) G_STMT_START{ \
|
||||
GstElement *current = ((GstBasicScheduler*)sched)->current; \
|
||||
if (current->post_run_func) \
|
||||
current->post_run_func (current); \
|
||||
SCHED (current)->current = NULL; \
|
||||
do_cothread_switch \
|
||||
(do_cothread_get_main \
|
||||
(((GstBasicScheduler*)sched)->context)); \
|
||||
}G_STMT_END
|
||||
|
||||
#define do_switch_from_main(entry) G_STMT_START{ \
|
||||
if (entry->pre_run_func) \
|
||||
entry->pre_run_func (entry); \
|
||||
SCHED (entry)->current = entry; \
|
||||
do_cothread_switch (GST_ELEMENT_THREADSTATE (entry)); \
|
||||
}G_STMT_END
|
||||
|
||||
static GType
|
||||
gst_basic_scheduler_get_type (void)
|
||||
{
|
||||
|
@ -301,9 +322,11 @@ gst_basic_scheduler_chain_wrapper (int argc, char *argv[])
|
|||
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
||||
GST_FLAG_UNSET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
||||
|
||||
/* this will return to cothread 0, so we need to unlock the current element */
|
||||
if (element->post_run_func)
|
||||
element->post_run_func (element);
|
||||
/* due to oddities in the cothreads code, when this function returns it will
|
||||
* switch to the main cothread. thus, we need to unlock the current element. */
|
||||
if (SCHED (element)->current->post_run_func)
|
||||
SCHED (element)->current->post_run_func (SCHED (element)->current);
|
||||
SCHED (element)->current = NULL;
|
||||
|
||||
GST_DEBUG_LEAVE ("(%d,'%s')", argc, name);
|
||||
gst_object_unref (GST_OBJECT (element));
|
||||
|
@ -346,6 +369,12 @@ gst_basic_scheduler_src_wrapper (int argc, char *argv[])
|
|||
|
||||
GST_FLAG_UNSET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
||||
|
||||
/* due to oddities in the cothreads code, when this function returns it will
|
||||
* switch to the main cothread. thus, we need to unlock the current element. */
|
||||
if (SCHED (element)->current->post_run_func)
|
||||
SCHED (element)->current->post_run_func (SCHED (element)->current);
|
||||
SCHED (element)->current = NULL;
|
||||
|
||||
GST_DEBUG_LEAVE ("");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1050,11 +1079,8 @@ static void
|
|||
gst_basic_scheduler_yield (GstScheduler *sched, GstElement *element)
|
||||
{
|
||||
if (GST_ELEMENT_IS_COTHREAD_STOPPING (element)) {
|
||||
if (element->post_run_func)
|
||||
element->post_run_func (element);
|
||||
|
||||
SCHED (element)->current = NULL;
|
||||
do_cothread_switch (do_cothread_get_main (((GstBasicScheduler *) sched)->context));
|
||||
|
||||
do_switch_to_main (sched);
|
||||
|
||||
/* no need to do a pre_run, the cothread is stopping */
|
||||
}
|
||||
|
@ -1063,15 +1089,9 @@ gst_basic_scheduler_yield (GstScheduler *sched, GstElement *element)
|
|||
static gboolean
|
||||
gst_basic_scheduler_interrupt (GstScheduler *sched, GstElement *element)
|
||||
{
|
||||
GstElement *current = SCHED (element)->current;
|
||||
|
||||
GST_FLAG_SET (element, GST_ELEMENT_COTHREAD_STOPPING);
|
||||
|
||||
if (current->post_run_func)
|
||||
current->post_run_func (current);
|
||||
|
||||
SCHED (element)->current = NULL;
|
||||
do_cothread_switch (do_cothread_get_main (((GstBasicScheduler *) sched)->context));
|
||||
do_switch_to_main (sched);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1090,11 +1110,7 @@ gst_basic_scheduler_error (GstScheduler *sched, GstElement *element)
|
|||
|
||||
GST_SCHEDULER_STATE (sched) = GST_SCHEDULER_STATE_ERROR;
|
||||
|
||||
if (element->post_run_func)
|
||||
element->post_run_func (element);
|
||||
|
||||
SCHED (element)->current = NULL;
|
||||
do_cothread_switch (do_cothread_get_main (((GstBasicScheduler *) sched)->context));
|
||||
do_switch_to_main (sched);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1269,17 +1285,9 @@ gst_basic_scheduler_iterate (GstScheduler * sched)
|
|||
GST_DEBUG (GST_CAT_DATAFLOW, "set COTHREAD_STOPPING flag on \"%s\"(@%p)",
|
||||
GST_ELEMENT_NAME (entry), entry);
|
||||
if (GST_ELEMENT_THREADSTATE (entry)) {
|
||||
if (entry->pre_run_func)
|
||||
entry->pre_run_func (entry);
|
||||
|
||||
bsched->current = entry;
|
||||
do_switch_from_main (entry);
|
||||
|
||||
do_cothread_switch (GST_ELEMENT_THREADSTATE (entry));
|
||||
|
||||
if (bsched->current && bsched->current->post_run_func) {
|
||||
bsched->current->post_run_func (bsched->current);
|
||||
}
|
||||
|
||||
state = GST_SCHEDULER_STATE (sched);
|
||||
/* if something changed, return - go on else */
|
||||
if (GST_FLAG_IS_SET(bsched, GST_BASIC_SCHEDULER_CHANGE) &&
|
||||
|
|
Loading…
Reference in a new issue