mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-09-01 01:33:52 +00:00
Remove memchunk benchmark stuff, this is taken over by GLib bug 118439.
Original commit message from CVS: 2005-09-26 Andy Wingo <wingo@pobox.com> * configure.ac: * tests/Makefile.am: * tests/memchunk: Remove memchunk benchmark stuff, this is taken over by GLib bug 118439. * gst/base/gstbasesink.c (gst_base_sink_wait): Factor out the wait routines to a function. * docs/libs/gstreamer-libs-sections.txt: I am a good person today. * libs/gst/controller/gsthelper.c: * libs/gst/controller/gstcontroller.h (gst_controller_sync_values) (gst_object_sync_values): Renamed from sink_values. Ugh. * libs/gst/controller/gsthelper.c: Update for __gst_controller_key. * libs/gst/controller/gstcontroller.c (__gst_controller_key): Renamed from controller_key, as it is exported. * gst/gstvalue.c (_gst_value_initialize): Fake out the compiler.
This commit is contained in:
parent
b98900a0a0
commit
2f46ef713d
16 changed files with 108 additions and 616 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
||||||
|
2005-09-26 Andy Wingo <wingo@pobox.com>
|
||||||
|
|
||||||
|
* configure.ac:
|
||||||
|
* tests/Makefile.am:
|
||||||
|
* tests/memchunk: Remove memchunk benchmark stuff, this is taken
|
||||||
|
over by GLib bug 118439.
|
||||||
|
|
||||||
|
* gst/base/gstbasesink.c (gst_base_sink_wait): Factor out the wait
|
||||||
|
routines to a function.
|
||||||
|
|
||||||
|
* docs/libs/gstreamer-libs-sections.txt: I am a good person today.
|
||||||
|
|
||||||
|
* libs/gst/controller/gsthelper.c:
|
||||||
|
* libs/gst/controller/gstcontroller.h (gst_controller_sync_values)
|
||||||
|
(gst_object_sync_values): Renamed from sink_values. Ugh.
|
||||||
|
|
||||||
|
* libs/gst/controller/gsthelper.c: Update for __gst_controller_key.
|
||||||
|
|
||||||
|
* libs/gst/controller/gstcontroller.c (__gst_controller_key):
|
||||||
|
Renamed from controller_key, as it is exported.
|
||||||
|
|
||||||
|
* gst/gstvalue.c (_gst_value_initialize): Fake out the compiler.
|
||||||
|
|
||||||
2005-09-26 Thomas Vander Stichele <thomas at apestaart dot org>
|
2005-09-26 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||||
|
|
||||||
* gst/Makefile.am:
|
* gst/Makefile.am:
|
||||||
|
|
|
@ -657,7 +657,6 @@ po/Makefile.in
|
||||||
check/Makefile
|
check/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
tests/instantiate/Makefile
|
tests/instantiate/Makefile
|
||||||
tests/memchunk/Makefile
|
|
||||||
tests/muxing/Makefile
|
tests/muxing/Makefile
|
||||||
tests/seeking/Makefile
|
tests/seeking/Makefile
|
||||||
tests/sched/Makefile
|
tests/sched/Makefile
|
||||||
|
|
|
@ -58,7 +58,7 @@ gst_controller_set_from_list
|
||||||
gst_controller_unset
|
gst_controller_unset
|
||||||
gst_controller_get
|
gst_controller_get
|
||||||
gst_controller_get_all
|
gst_controller_get_all
|
||||||
gst_controller_sink_values
|
gst_controller_sync_values
|
||||||
gst_controller_get_value_arrays
|
gst_controller_get_value_arrays
|
||||||
gst_controller_get_value_array
|
gst_controller_get_value_array
|
||||||
gst_controller_set_interpolation_mode
|
gst_controller_set_interpolation_mode
|
||||||
|
@ -86,7 +86,7 @@ gst_object_control_properties
|
||||||
gst_object_uncontrol_properties
|
gst_object_uncontrol_properties
|
||||||
gst_object_get_controller
|
gst_object_get_controller
|
||||||
gst_object_set_controller
|
gst_object_set_controller
|
||||||
gst_object_sink_values
|
gst_object_sync_values
|
||||||
gst_object_get_value_arrays
|
gst_object_get_value_arrays
|
||||||
gst_object_get_value_array
|
gst_object_get_value_array
|
||||||
<SUBSECTION Standard>
|
<SUBSECTION Standard>
|
||||||
|
|
|
@ -886,6 +886,29 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* with STREAM_LOCK and LOCK*/
|
||||||
|
static GstClockReturn
|
||||||
|
gst_base_sink_wait (GstBaseSink * basesink, GstClockTime time)
|
||||||
|
{
|
||||||
|
GstClockReturn ret;
|
||||||
|
|
||||||
|
/* clock_id should be NULL outside of this function */
|
||||||
|
g_assert (basesink->clock_id == NULL);
|
||||||
|
g_assert (GST_CLOCK_TIME_IS_VALID (time));
|
||||||
|
|
||||||
|
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock, time);
|
||||||
|
|
||||||
|
/* release the object lock while waiting */
|
||||||
|
GST_UNLOCK (basesink);
|
||||||
|
ret = gst_clock_id_wait (basesink->clock_id, NULL);
|
||||||
|
GST_LOCK (basesink);
|
||||||
|
|
||||||
|
gst_clock_id_unref (basesink->clock_id);
|
||||||
|
basesink->clock_id = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* perform synchronisation on a buffer
|
/* perform synchronisation on a buffer
|
||||||
*
|
*
|
||||||
* 1) check if we have a clock, if not, do nothing
|
* 1) check if we have a clock, if not, do nothing
|
||||||
|
@ -957,30 +980,22 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
|
||||||
GstClockTime base_time;
|
GstClockTime base_time;
|
||||||
|
|
||||||
GST_LOCK (basesink);
|
GST_LOCK (basesink);
|
||||||
|
|
||||||
base_time = GST_ELEMENT (basesink)->base_time;
|
base_time = GST_ELEMENT (basesink)->base_time;
|
||||||
|
|
||||||
GST_LOG_OBJECT (basesink,
|
GST_LOG_OBJECT (basesink,
|
||||||
"waiting for clock, base time %" GST_TIME_FORMAT,
|
"waiting for clock, base time %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (base_time));
|
GST_TIME_ARGS (base_time));
|
||||||
|
|
||||||
/* save clock id so that we can unlock it if needed */
|
|
||||||
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
|
|
||||||
stream_start + base_time);
|
|
||||||
/* also save end_time of this buffer so that we can wait
|
/* also save end_time of this buffer so that we can wait
|
||||||
* to signal EOS */
|
* to signal EOS */
|
||||||
if (end_valid)
|
if (end_valid)
|
||||||
basesink->end_time = stream_end + base_time;
|
basesink->end_time = stream_end + base_time;
|
||||||
else
|
else
|
||||||
basesink->end_time = GST_CLOCK_TIME_NONE;
|
basesink->end_time = GST_CLOCK_TIME_NONE;
|
||||||
GST_UNLOCK (basesink);
|
|
||||||
|
|
||||||
ret = gst_clock_id_wait (basesink->clock_id, NULL);
|
ret = gst_base_sink_wait (basesink, stream_start + base_time);
|
||||||
|
|
||||||
GST_LOCK (basesink);
|
|
||||||
if (basesink->clock_id) {
|
|
||||||
gst_clock_id_unref (basesink->clock_id);
|
|
||||||
basesink->clock_id = NULL;
|
|
||||||
}
|
|
||||||
GST_UNLOCK (basesink);
|
GST_UNLOCK (basesink);
|
||||||
|
|
||||||
GST_LOG_OBJECT (basesink, "clock entry done: %d", ret);
|
GST_LOG_OBJECT (basesink, "clock entry done: %d", ret);
|
||||||
|
@ -1016,17 +1031,7 @@ gst_base_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
|
||||||
if (basesink->clock) {
|
if (basesink->clock) {
|
||||||
/* wait for last buffer to finish if we have a valid end time */
|
/* wait for last buffer to finish if we have a valid end time */
|
||||||
if (GST_CLOCK_TIME_IS_VALID (basesink->end_time)) {
|
if (GST_CLOCK_TIME_IS_VALID (basesink->end_time)) {
|
||||||
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
|
gst_base_sink_wait (basesink, basesink->end_time);
|
||||||
basesink->end_time);
|
|
||||||
GST_UNLOCK (basesink);
|
|
||||||
|
|
||||||
gst_clock_id_wait (basesink->clock_id, NULL);
|
|
||||||
|
|
||||||
GST_LOCK (basesink);
|
|
||||||
if (basesink->clock_id) {
|
|
||||||
gst_clock_id_unref (basesink->clock_id);
|
|
||||||
basesink->clock_id = NULL;
|
|
||||||
}
|
|
||||||
basesink->end_time = GST_CLOCK_TIME_NONE;
|
basesink->end_time = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3392,6 +3392,11 @@ _gst_value_initialize (void)
|
||||||
gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
|
gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
|
||||||
GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
|
GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
|
||||||
|
|
||||||
|
#if GLIB_CHECK_VERSION(2,8,0)
|
||||||
|
/* see bug #317246 */
|
||||||
|
GST_LOG ("Faking out the compiler: %d", G_TYPE_DATE);
|
||||||
|
#endif
|
||||||
|
|
||||||
gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
|
gst_value_register_union_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
|
||||||
gst_value_union_int_int_range);
|
gst_value_union_int_int_range);
|
||||||
gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
|
gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
|
||||||
|
|
|
@ -886,6 +886,29 @@ gst_base_sink_get_times (GstBaseSink * basesink, GstBuffer * buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* with STREAM_LOCK and LOCK*/
|
||||||
|
static GstClockReturn
|
||||||
|
gst_base_sink_wait (GstBaseSink * basesink, GstClockTime time)
|
||||||
|
{
|
||||||
|
GstClockReturn ret;
|
||||||
|
|
||||||
|
/* clock_id should be NULL outside of this function */
|
||||||
|
g_assert (basesink->clock_id == NULL);
|
||||||
|
g_assert (GST_CLOCK_TIME_IS_VALID (time));
|
||||||
|
|
||||||
|
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock, time);
|
||||||
|
|
||||||
|
/* release the object lock while waiting */
|
||||||
|
GST_UNLOCK (basesink);
|
||||||
|
ret = gst_clock_id_wait (basesink->clock_id, NULL);
|
||||||
|
GST_LOCK (basesink);
|
||||||
|
|
||||||
|
gst_clock_id_unref (basesink->clock_id);
|
||||||
|
basesink->clock_id = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* perform synchronisation on a buffer
|
/* perform synchronisation on a buffer
|
||||||
*
|
*
|
||||||
* 1) check if we have a clock, if not, do nothing
|
* 1) check if we have a clock, if not, do nothing
|
||||||
|
@ -957,30 +980,22 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
|
||||||
GstClockTime base_time;
|
GstClockTime base_time;
|
||||||
|
|
||||||
GST_LOCK (basesink);
|
GST_LOCK (basesink);
|
||||||
|
|
||||||
base_time = GST_ELEMENT (basesink)->base_time;
|
base_time = GST_ELEMENT (basesink)->base_time;
|
||||||
|
|
||||||
GST_LOG_OBJECT (basesink,
|
GST_LOG_OBJECT (basesink,
|
||||||
"waiting for clock, base time %" GST_TIME_FORMAT,
|
"waiting for clock, base time %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (base_time));
|
GST_TIME_ARGS (base_time));
|
||||||
|
|
||||||
/* save clock id so that we can unlock it if needed */
|
|
||||||
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
|
|
||||||
stream_start + base_time);
|
|
||||||
/* also save end_time of this buffer so that we can wait
|
/* also save end_time of this buffer so that we can wait
|
||||||
* to signal EOS */
|
* to signal EOS */
|
||||||
if (end_valid)
|
if (end_valid)
|
||||||
basesink->end_time = stream_end + base_time;
|
basesink->end_time = stream_end + base_time;
|
||||||
else
|
else
|
||||||
basesink->end_time = GST_CLOCK_TIME_NONE;
|
basesink->end_time = GST_CLOCK_TIME_NONE;
|
||||||
GST_UNLOCK (basesink);
|
|
||||||
|
|
||||||
ret = gst_clock_id_wait (basesink->clock_id, NULL);
|
ret = gst_base_sink_wait (basesink, stream_start + base_time);
|
||||||
|
|
||||||
GST_LOCK (basesink);
|
|
||||||
if (basesink->clock_id) {
|
|
||||||
gst_clock_id_unref (basesink->clock_id);
|
|
||||||
basesink->clock_id = NULL;
|
|
||||||
}
|
|
||||||
GST_UNLOCK (basesink);
|
GST_UNLOCK (basesink);
|
||||||
|
|
||||||
GST_LOG_OBJECT (basesink, "clock entry done: %d", ret);
|
GST_LOG_OBJECT (basesink, "clock entry done: %d", ret);
|
||||||
|
@ -1016,17 +1031,7 @@ gst_base_sink_handle_event (GstBaseSink * basesink, GstEvent * event)
|
||||||
if (basesink->clock) {
|
if (basesink->clock) {
|
||||||
/* wait for last buffer to finish if we have a valid end time */
|
/* wait for last buffer to finish if we have a valid end time */
|
||||||
if (GST_CLOCK_TIME_IS_VALID (basesink->end_time)) {
|
if (GST_CLOCK_TIME_IS_VALID (basesink->end_time)) {
|
||||||
basesink->clock_id = gst_clock_new_single_shot_id (basesink->clock,
|
gst_base_sink_wait (basesink, basesink->end_time);
|
||||||
basesink->end_time);
|
|
||||||
GST_UNLOCK (basesink);
|
|
||||||
|
|
||||||
gst_clock_id_wait (basesink->clock_id, NULL);
|
|
||||||
|
|
||||||
GST_LOCK (basesink);
|
|
||||||
if (basesink->clock_id) {
|
|
||||||
gst_clock_id_unref (basesink->clock_id);
|
|
||||||
basesink->clock_id = NULL;
|
|
||||||
}
|
|
||||||
basesink->end_time = GST_CLOCK_TIME_NONE;
|
basesink->end_time = GST_CLOCK_TIME_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
* </para></listitem>
|
* </para></listitem>
|
||||||
* <listitem><para>
|
* <listitem><para>
|
||||||
* when processing data (get, chain, loop function) at the beginning call
|
* when processing data (get, chain, loop function) at the beginning call
|
||||||
* gst_object_sink_values(element,timestamp).
|
* gst_object_sync_values(element,timestamp).
|
||||||
* This will made the controller to update all gobject properties that are under
|
* This will made the controller to update all gobject properties that are under
|
||||||
* control with the current values based on timestamp.
|
* control with the current values based on timestamp.
|
||||||
* </para></listitem>
|
* </para></listitem>
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
static GObjectClass *parent_class = NULL;
|
static GObjectClass *parent_class = NULL;
|
||||||
GQuark controller_key;
|
GQuark __gst_controller_key;
|
||||||
|
|
||||||
|
|
||||||
/* imports from gst-interpolation.c */
|
/* imports from gst-interpolation.c */
|
||||||
|
@ -94,7 +94,7 @@ on_object_controlled_property_changed (const GObject * object, GParamSpec * arg,
|
||||||
|
|
||||||
GST_INFO ("notify for '%s'", prop->name);
|
GST_INFO ("notify for '%s'", prop->name);
|
||||||
|
|
||||||
ctrl = g_object_get_qdata (G_OBJECT (object), controller_key);
|
ctrl = g_object_get_qdata (G_OBJECT (object), __gst_controller_key);
|
||||||
g_return_if_fail (ctrl);
|
g_return_if_fail (ctrl);
|
||||||
|
|
||||||
if (g_mutex_trylock (ctrl->lock)) {
|
if (g_mutex_trylock (ctrl->lock)) {
|
||||||
|
@ -420,7 +420,7 @@ gst_controller_new_valist (GObject * object, va_list var_args)
|
||||||
GstParent will be in core after all.
|
GstParent will be in core after all.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
self = g_object_get_qdata (object, controller_key);
|
self = g_object_get_qdata (object, __gst_controller_key);
|
||||||
// create GstControlledProperty for each property
|
// create GstControlledProperty for each property
|
||||||
while ((name = va_arg (var_args, gchar *))) {
|
while ((name = va_arg (var_args, gchar *))) {
|
||||||
// test if this property isn't yet controlled
|
// test if this property isn't yet controlled
|
||||||
|
@ -432,7 +432,7 @@ gst_controller_new_valist (GObject * object, va_list var_args)
|
||||||
self = g_object_new (GST_TYPE_CONTROLLER, NULL);
|
self = g_object_new (GST_TYPE_CONTROLLER, NULL);
|
||||||
self->object = object;
|
self->object = object;
|
||||||
// store the controller
|
// store the controller
|
||||||
g_object_set_qdata (object, controller_key, self);
|
g_object_set_qdata (object, __gst_controller_key, self);
|
||||||
} else {
|
} else {
|
||||||
// increment ref-count (this causes red-count-leaks
|
// increment ref-count (this causes red-count-leaks
|
||||||
//self = g_object_ref (self);
|
//self = g_object_ref (self);
|
||||||
|
@ -730,7 +730,7 @@ gst_controller_get_all (GstController * self, gchar * property_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_controller_sink_values:
|
* gst_controller_sync_values:
|
||||||
* @self: the controller that handles the values
|
* @self: the controller that handles the values
|
||||||
* @timestamp: the time that should be processed
|
* @timestamp: the time that should be processed
|
||||||
*
|
*
|
||||||
|
@ -742,7 +742,7 @@ gst_controller_get_all (GstController * self, gchar * property_name)
|
||||||
* Since: 0.9
|
* Since: 0.9
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_controller_sink_values (GstController * self, GstClockTime timestamp)
|
gst_controller_sync_values (GstController * self, GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GstControlledProperty *prop;
|
GstControlledProperty *prop;
|
||||||
GList *node;
|
GList *node;
|
||||||
|
@ -752,7 +752,7 @@ gst_controller_sink_values (GstController * self, GstClockTime timestamp)
|
||||||
g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
|
g_return_val_if_fail (GST_IS_CONTROLLER (self), FALSE);
|
||||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
|
|
||||||
GST_INFO ("sink_values");
|
GST_INFO ("sync_values");
|
||||||
|
|
||||||
g_mutex_lock (self->lock);
|
g_mutex_lock (self->lock);
|
||||||
// go over the controlled properties of the controller
|
// go over the controlled properties of the controller
|
||||||
|
@ -954,7 +954,7 @@ _gst_controller_finalize (GObject * object)
|
||||||
}
|
}
|
||||||
g_mutex_free (self->lock);
|
g_mutex_free (self->lock);
|
||||||
/* remove controller from objects qdata list */
|
/* remove controller from objects qdata list */
|
||||||
g_object_set_qdata (self->object, controller_key, NULL);
|
g_object_set_qdata (self->object, __gst_controller_key, NULL);
|
||||||
|
|
||||||
if (G_OBJECT_CLASS (parent_class)->finalize)
|
if (G_OBJECT_CLASS (parent_class)->finalize)
|
||||||
(G_OBJECT_CLASS (parent_class)->finalize) (object);
|
(G_OBJECT_CLASS (parent_class)->finalize) (object);
|
||||||
|
@ -978,7 +978,7 @@ _gst_controller_class_init (GstControllerClass * klass)
|
||||||
|
|
||||||
gobject_class->finalize = _gst_controller_finalize;
|
gobject_class->finalize = _gst_controller_finalize;
|
||||||
|
|
||||||
controller_key = g_quark_from_string ("gst::controller");
|
__gst_controller_key = g_quark_from_string ("gst::controller");
|
||||||
|
|
||||||
// register properties
|
// register properties
|
||||||
// register signals
|
// register signals
|
||||||
|
|
|
@ -225,7 +225,7 @@ const GList *gst_controller_get_all (GstController * self,
|
||||||
gchar * property_name);
|
gchar * property_name);
|
||||||
|
|
||||||
|
|
||||||
gboolean gst_controller_sink_values (GstController * self,
|
gboolean gst_controller_sync_values (GstController * self,
|
||||||
GstClockTime timestamp);
|
GstClockTime timestamp);
|
||||||
|
|
||||||
gboolean gst_controller_get_value_arrays (GstController * self,
|
gboolean gst_controller_get_value_arrays (GstController * self,
|
||||||
|
@ -245,7 +245,7 @@ gboolean gst_object_uncontrol_properties (GObject * object, ...);
|
||||||
GstController *gst_object_get_controller (GObject * object);
|
GstController *gst_object_get_controller (GObject * object);
|
||||||
gboolean gst_object_set_controller (GObject * object, GstController * controller);
|
gboolean gst_object_set_controller (GObject * object, GstController * controller);
|
||||||
|
|
||||||
gboolean gst_object_sink_values (GObject * object, GstClockTime timestamp);
|
gboolean gst_object_sync_values (GObject * object, GstClockTime timestamp);
|
||||||
|
|
||||||
gboolean gst_object_get_value_arrays (GObject * object,
|
gboolean gst_object_get_value_arrays (GObject * object,
|
||||||
GstClockTime timestamp, GSList * value_arrays);
|
GstClockTime timestamp, GSList * value_arrays);
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#define GST_CAT_DEFAULT gst_controller_debug
|
#define GST_CAT_DEFAULT gst_controller_debug
|
||||||
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
extern GQuark controller_key;
|
extern GQuark __gst_controller_key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_object_control_properties:
|
* gst_object_control_properties:
|
||||||
|
@ -88,7 +88,7 @@ gst_object_uncontrol_properties (GObject * object, ...)
|
||||||
|
|
||||||
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
if ((ctrl = g_object_get_qdata (object, controller_key))) {
|
if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
|
||||||
va_list var_args;
|
va_list var_args;
|
||||||
|
|
||||||
va_start (var_args, object);
|
va_start (var_args, object);
|
||||||
|
@ -110,7 +110,7 @@ gst_object_get_controller (GObject * object)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
return (g_object_get_qdata (object, controller_key));
|
return (g_object_get_qdata (object, __gst_controller_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,33 +131,33 @@ gst_object_set_controller (GObject * object, GstController * controller)
|
||||||
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (controller, FALSE);
|
g_return_val_if_fail (controller, FALSE);
|
||||||
|
|
||||||
if (!(ctrl = g_object_get_qdata (object, controller_key))) {
|
if (!(ctrl = g_object_get_qdata (object, __gst_controller_key))) {
|
||||||
g_object_set_qdata (object, controller_key, controller);
|
g_object_set_qdata (object, __gst_controller_key, controller);
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
}
|
}
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_object_sink_values:
|
* gst_object_sync_values:
|
||||||
* @object: the object that has controlled properties
|
* @object: the object that has controlled properties
|
||||||
* @timestamp: the time that should be processed
|
* @timestamp: the time that should be processed
|
||||||
*
|
*
|
||||||
* Convenience function for GObject
|
* Convenience function for GObject
|
||||||
*
|
*
|
||||||
* Returns: same thing as gst_controller_sink_values()
|
* Returns: same thing as gst_controller_sync_values()
|
||||||
* Since: 0.9
|
* Since: 0.9
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_object_sink_values (GObject * object, GstClockTime timestamp)
|
gst_object_sync_values (GObject * object, GstClockTime timestamp)
|
||||||
{
|
{
|
||||||
GstController *ctrl = NULL;
|
GstController *ctrl = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
|
|
||||||
if ((ctrl = g_object_get_qdata (object, controller_key))) {
|
if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
|
||||||
return gst_controller_sink_values (ctrl, timestamp);
|
return gst_controller_sync_values (ctrl, timestamp);
|
||||||
}
|
}
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ gst_object_get_value_arrays (GObject * object, GstClockTime timestamp,
|
||||||
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
|
|
||||||
if ((ctrl = g_object_get_qdata (object, controller_key))) {
|
if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
|
||||||
return gst_controller_get_value_arrays (ctrl, timestamp, value_arrays);
|
return gst_controller_get_value_arrays (ctrl, timestamp, value_arrays);
|
||||||
}
|
}
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
|
@ -220,7 +220,7 @@ gst_object_get_value_array (GObject * object, GstClockTime timestamp,
|
||||||
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
g_return_val_if_fail (GST_CLOCK_TIME_IS_VALID (timestamp), FALSE);
|
||||||
|
|
||||||
if ((ctrl = g_object_get_qdata (object, controller_key))) {
|
if ((ctrl = g_object_get_qdata (object, __gst_controller_key))) {
|
||||||
return gst_controller_get_value_array (ctrl, timestamp, value_array);
|
return gst_controller_get_value_array (ctrl, timestamp, value_array);
|
||||||
}
|
}
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
SUBDIRS = instantiate memchunk muxing sched threadstate seeking
|
SUBDIRS = instantiate muxing sched threadstate seeking
|
||||||
|
|
||||||
if GST_DISABLE_TRACE
|
if GST_DISABLE_TRACE
|
||||||
LAT =
|
LAT =
|
||||||
|
@ -15,4 +15,4 @@ LIBS = $(GST_OBJ_LIBS) \
|
||||||
$(top_builddir)/gst/base/libgstbase-@GST_MAJORMINOR@.la
|
$(top_builddir)/gst/base/libgstbase-@GST_MAJORMINOR@.la
|
||||||
|
|
||||||
EXTRA_DIST = README
|
EXTRA_DIST = README
|
||||||
DIST_SUBDIRS= instantiate memchunk muxing sched threadstate seeking
|
DIST_SUBDIRS= instantiate muxing sched threadstate seeking
|
||||||
|
|
5
tests/memchunk/.gitignore
vendored
5
tests/memchunk/.gitignore
vendored
|
@ -1,5 +0,0 @@
|
||||||
gmemchunktest
|
|
||||||
gstmemchunktest
|
|
||||||
*.bb
|
|
||||||
*.bbg
|
|
||||||
*.da
|
|
|
@ -1,7 +0,0 @@
|
||||||
noinst_PROGRAMS = gmemchunktest gstmemchunktest
|
|
||||||
|
|
||||||
gmemchunktest_SOURCES = gmemchunktest.c
|
|
||||||
gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h
|
|
||||||
|
|
||||||
LDADD = $(GST_OBJ_LIBS)
|
|
||||||
AM_CFLAGS = $(GST_OBJ_CFLAGS)
|
|
|
@ -1,252 +0,0 @@
|
||||||
/* GStreamer
|
|
||||||
* Copyright (C) 2005 Andy Wingo <wingo at pobox.com>
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Library General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Library General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Library General Public
|
|
||||||
* License along with this library; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <glib.h>
|
|
||||||
#include <gmodule.h>
|
|
||||||
#include <gst/gstmemchunk.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_THREADS 100
|
|
||||||
#define CHUNK_SIZE 32
|
|
||||||
#define GMEMCHUNK_THREADSAFE
|
|
||||||
|
|
||||||
|
|
||||||
typedef gpointer (*alloc_func_t) (void);
|
|
||||||
typedef void (*free_func_t) (gpointer);
|
|
||||||
|
|
||||||
|
|
||||||
static gint num_allocs;
|
|
||||||
static gint num_threads;
|
|
||||||
static alloc_func_t _alloc = NULL;
|
|
||||||
static free_func_t _free = NULL;
|
|
||||||
|
|
||||||
static GMemChunk *_gmemchunk;
|
|
||||||
static GMutex *_gmemchunklock;
|
|
||||||
static GstMemChunk *_gstmemchunk;
|
|
||||||
|
|
||||||
static GCond *ready_cond;
|
|
||||||
static GCond *start_cond;
|
|
||||||
static GMutex *sync_mutex;
|
|
||||||
|
|
||||||
|
|
||||||
static gdouble
|
|
||||||
get_current_time (void)
|
|
||||||
{
|
|
||||||
GTimeVal tv;
|
|
||||||
|
|
||||||
g_get_current_time (&tv);
|
|
||||||
return tv.tv_sec + ((gdouble) tv.tv_usec) / G_USEC_PER_SEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GMemChunk implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gpointer
|
|
||||||
gmemchunk_alloc (void)
|
|
||||||
{
|
|
||||||
gpointer ret;
|
|
||||||
|
|
||||||
#ifdef GMEMCHUNK_THREADSAFE
|
|
||||||
g_mutex_lock (_gmemchunklock);
|
|
||||||
#endif
|
|
||||||
ret = g_mem_chunk_alloc (_gmemchunk);
|
|
||||||
#ifdef GMEMCHUNK_THREADSAFE
|
|
||||||
g_mutex_unlock (_gmemchunklock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gmemchunk_free (gpointer chunk)
|
|
||||||
{
|
|
||||||
#ifdef GMEMCHUNK_THREADSAFE
|
|
||||||
g_mutex_lock (_gmemchunklock);
|
|
||||||
#endif
|
|
||||||
g_mem_chunk_free (_gmemchunk, chunk);
|
|
||||||
#ifdef GMEMCHUNK_THREADSAFE
|
|
||||||
g_mutex_unlock (_gmemchunklock);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* GstMemChunk implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gpointer
|
|
||||||
gstmemchunk_alloc (void)
|
|
||||||
{
|
|
||||||
return gst_mem_chunk_alloc (_gstmemchunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gstmemchunk_free (gpointer chunk)
|
|
||||||
{
|
|
||||||
gst_mem_chunk_free (_gstmemchunk, chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normal (malloc/free) implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
static gpointer
|
|
||||||
normal_alloc (void)
|
|
||||||
{
|
|
||||||
return g_malloc (CHUNK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
normal_free (gpointer chunk)
|
|
||||||
{
|
|
||||||
g_free (chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normal (malloc/free) implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
void *(*_google_malloc) (gsize) = NULL;
|
|
||||||
void (*_google_free) (void *) = NULL;
|
|
||||||
static gpointer
|
|
||||||
google_alloc (void)
|
|
||||||
{
|
|
||||||
return _google_malloc (CHUNK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
google_free (gpointer chunk)
|
|
||||||
{
|
|
||||||
_google_free (chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The test
|
|
||||||
*/
|
|
||||||
|
|
||||||
void *
|
|
||||||
worker_thread (void *threadid)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
gpointer chunk;
|
|
||||||
|
|
||||||
g_mutex_lock (sync_mutex);
|
|
||||||
g_cond_signal (ready_cond);
|
|
||||||
g_cond_wait (start_cond, sync_mutex);
|
|
||||||
g_mutex_unlock (sync_mutex);
|
|
||||||
|
|
||||||
for (i = 0; i < num_allocs; i++) {
|
|
||||||
chunk = _alloc ();
|
|
||||||
_free (chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gdouble
|
|
||||||
run_test (alloc_func_t alloc_func, free_func_t free_func)
|
|
||||||
{
|
|
||||||
gdouble start, end;
|
|
||||||
GThread *threads[MAX_THREADS];
|
|
||||||
GError *error;
|
|
||||||
int t;
|
|
||||||
|
|
||||||
_alloc = alloc_func;
|
|
||||||
_free = free_func;
|
|
||||||
|
|
||||||
g_mutex_lock (sync_mutex);
|
|
||||||
for (t = 0; t < num_threads; t++) {
|
|
||||||
error = NULL;
|
|
||||||
threads[t] =
|
|
||||||
g_thread_create (worker_thread, GINT_TO_POINTER (t), TRUE, &error);
|
|
||||||
g_assert (threads[t]);
|
|
||||||
g_cond_wait (ready_cond, sync_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_cond_broadcast (start_cond);
|
|
||||||
start = get_current_time ();
|
|
||||||
g_mutex_unlock (sync_mutex);
|
|
||||||
|
|
||||||
for (t = 0; t < num_threads; t++)
|
|
||||||
g_thread_join (threads[t]);
|
|
||||||
|
|
||||||
end = get_current_time ();
|
|
||||||
|
|
||||||
return end - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
gint
|
|
||||||
main (gint argc, gchar * argv[])
|
|
||||||
{
|
|
||||||
gdouble time;
|
|
||||||
GModule *google_lib;
|
|
||||||
|
|
||||||
g_thread_init (NULL);
|
|
||||||
|
|
||||||
ready_cond = g_cond_new ();
|
|
||||||
start_cond = g_cond_new ();
|
|
||||||
sync_mutex = g_mutex_new ();
|
|
||||||
|
|
||||||
if (argc != 3) {
|
|
||||||
g_print ("usage: %s <num_threads> <num_allocs>\n", argv[0]);
|
|
||||||
exit (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
num_threads = atoi (argv[1]);
|
|
||||||
num_allocs = atoi (argv[2]);
|
|
||||||
g_assert (num_threads > 0);
|
|
||||||
g_assert (num_allocs > 0);
|
|
||||||
|
|
||||||
_gmemchunk =
|
|
||||||
g_mem_chunk_new ("test", CHUNK_SIZE, CHUNK_SIZE * 16, G_ALLOC_ONLY);
|
|
||||||
_gmemchunklock = g_mutex_new ();
|
|
||||||
_gstmemchunk =
|
|
||||||
gst_mem_chunk_new ("test", CHUNK_SIZE, CHUNK_SIZE * 16, G_ALLOC_ONLY);
|
|
||||||
|
|
||||||
g_print ("%d alloc+frees X %d threads\n", num_allocs, num_threads);
|
|
||||||
time = run_test (gmemchunk_alloc, gmemchunk_free);
|
|
||||||
g_print ("%fs (%fs/thread) - GMemChunk\n", time, time / num_threads);
|
|
||||||
time = run_test (gstmemchunk_alloc, gstmemchunk_free);
|
|
||||||
g_print ("%fs (%fs/thread) - GstMemChunk\n", time, time / num_threads);
|
|
||||||
time = run_test (normal_alloc, normal_free);
|
|
||||||
g_print ("%fs (%fs/thread) - g_malloc/g_free\n", time, time / num_threads);
|
|
||||||
|
|
||||||
google_lib = g_module_open ("libtcmalloc.so", G_MODULE_BIND_LOCAL);
|
|
||||||
if (google_lib) {
|
|
||||||
gpointer sym;
|
|
||||||
|
|
||||||
g_module_symbol (google_lib, "malloc", &sym);
|
|
||||||
g_assert (sym);
|
|
||||||
_google_malloc = sym;
|
|
||||||
g_module_symbol (google_lib, "free", &sym);
|
|
||||||
g_assert (sym);
|
|
||||||
_google_free = sym;
|
|
||||||
time = run_test (google_alloc, google_free);
|
|
||||||
g_print ("%fs (%fs/thread) - google malloc/free\n", time,
|
|
||||||
time / num_threads);
|
|
||||||
} else {
|
|
||||||
g_print ("google malloc unavailable: %s\n", g_module_error ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* g_mem_chunk_info (); */
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,162 +0,0 @@
|
||||||
#include <string.h> /* memset */
|
|
||||||
#include <stdlib.h> /* memset */
|
|
||||||
#include "gstmemchunk.h"
|
|
||||||
|
|
||||||
#ifdef __SMP__
|
|
||||||
#define CHUNK_LOCK "lock ; "
|
|
||||||
#else
|
|
||||||
#define CHUNK_LOCK ""
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GST_MEM_CHUNK_AREA(chunk) (((GstMemChunkElement*)(chunk))->area)
|
|
||||||
#define GST_MEM_CHUNK_DATA(chunk) ((gpointer)(((GstMemChunkElement*)(chunk)) + 1))
|
|
||||||
#define GST_MEM_CHUNK_LINK(mem) ((GstMemChunkElement*)((guint8*)(mem) - sizeof (GstMemChunkElement)))
|
|
||||||
|
|
||||||
/*******************************************************
|
|
||||||
* area size
|
|
||||||
* +-----------------------------------------+
|
|
||||||
* chunk size
|
|
||||||
* +------------+
|
|
||||||
*
|
|
||||||
* !next!data... !next!data.... !next!data...
|
|
||||||
* ! ^ ! ^ !
|
|
||||||
* +-------------+ +------------+ +---> NULL
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static gboolean
|
|
||||||
populate (GstMemChunk * mem_chunk)
|
|
||||||
{
|
|
||||||
guint8 *area;
|
|
||||||
gint i;
|
|
||||||
|
|
||||||
if (mem_chunk->cleanup)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
area = (guint8 *) g_malloc (mem_chunk->area_size);
|
|
||||||
g_print ("alloc %p\n", area);
|
|
||||||
|
|
||||||
for (i = 0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
|
|
||||||
GST_MEM_CHUNK_AREA (area + i) = (GstMemChunkElement *) area;
|
|
||||||
gst_mem_chunk_free (mem_chunk, GST_MEM_CHUNK_DATA (area + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GstMemChunk *
|
|
||||||
gst_mem_chunk_new (gchar * name, gint atom_size, gulong area_size, gint type)
|
|
||||||
{
|
|
||||||
GstMemChunk *mem_chunk;
|
|
||||||
|
|
||||||
g_return_val_if_fail (atom_size > 0, NULL);
|
|
||||||
g_return_val_if_fail (area_size >= atom_size, NULL);
|
|
||||||
|
|
||||||
mem_chunk = g_malloc (sizeof (GstMemChunk));
|
|
||||||
|
|
||||||
mem_chunk->chunk_size = atom_size + sizeof (GstMemChunkElement);
|
|
||||||
area_size = (area_size / atom_size) * mem_chunk->chunk_size;
|
|
||||||
|
|
||||||
mem_chunk->name = g_strdup (name);
|
|
||||||
mem_chunk->free = NULL;
|
|
||||||
mem_chunk->cnt = 0;
|
|
||||||
mem_chunk->atom_size = atom_size;
|
|
||||||
mem_chunk->area_size = area_size;
|
|
||||||
mem_chunk->cleanup = FALSE;
|
|
||||||
|
|
||||||
populate (mem_chunk);
|
|
||||||
|
|
||||||
return mem_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
free_area (gpointer key, gpointer value, gpointer user_data)
|
|
||||||
{
|
|
||||||
g_print ("free %p\n", key);
|
|
||||||
g_free (key);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gst_mem_chunk_destroy (GstMemChunk * mem_chunk)
|
|
||||||
{
|
|
||||||
GHashTable *elements = g_hash_table_new (NULL, NULL);
|
|
||||||
gpointer data;
|
|
||||||
|
|
||||||
mem_chunk->cleanup = TRUE;
|
|
||||||
|
|
||||||
data = gst_mem_chunk_alloc (mem_chunk);
|
|
||||||
while (data) {
|
|
||||||
GstMemChunkElement *elem = GST_MEM_CHUNK_LINK (data);
|
|
||||||
|
|
||||||
g_hash_table_insert (elements, GST_MEM_CHUNK_AREA (elem), NULL);
|
|
||||||
|
|
||||||
data = gst_mem_chunk_alloc (mem_chunk);
|
|
||||||
}
|
|
||||||
g_hash_table_foreach_remove (elements, free_area, NULL);
|
|
||||||
|
|
||||||
g_hash_table_destroy (elements);
|
|
||||||
g_free (mem_chunk->name);
|
|
||||||
g_free (mem_chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpointer
|
|
||||||
gst_mem_chunk_alloc (GstMemChunk * mem_chunk)
|
|
||||||
{
|
|
||||||
GstMemChunkElement *chunk = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (mem_chunk != NULL, NULL);
|
|
||||||
|
|
||||||
again:
|
|
||||||
#ifdef HAVE_I386
|
|
||||||
__asm__ __volatile__ (" testl %%eax, %%eax \n\t" " jz 20f \n" "10: \t" " movl (%%eax), %%ebx \n\t" " movl %%edx, %%ecx \n\t" " incl %%ecx \n\t" CHUNK_LOCK "cmpxchg8b %1 \n\t" " jz 20f \n\t" " testl %%eax, %%eax \n\t" " jnz 10b \n" "20:\t":"=a" (chunk)
|
|
||||||
: "m" (*mem_chunk), "a" (mem_chunk->free), "d" (mem_chunk->cnt)
|
|
||||||
: "ecx", "ebx");
|
|
||||||
#else
|
|
||||||
fprintf (stderr, "This only compiles correctly on i386. Sorry\n");
|
|
||||||
abort ();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!chunk) {
|
|
||||||
/*g_print ("extending\n"); */
|
|
||||||
if (populate (mem_chunk))
|
|
||||||
goto again;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return GST_MEM_CHUNK_DATA (chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpointer
|
|
||||||
gst_mem_chunk_alloc0 (GstMemChunk * mem_chunk)
|
|
||||||
{
|
|
||||||
gpointer mem = gst_mem_chunk_alloc (mem_chunk);
|
|
||||||
|
|
||||||
if (mem)
|
|
||||||
memset (mem, 0, mem_chunk->atom_size);
|
|
||||||
|
|
||||||
return mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
gst_mem_chunk_free (GstMemChunk * mem_chunk, gpointer mem)
|
|
||||||
{
|
|
||||||
GstMemChunkElement *chunk;
|
|
||||||
|
|
||||||
g_return_if_fail (mem_chunk != NULL);
|
|
||||||
g_return_if_fail (mem != NULL);
|
|
||||||
|
|
||||||
chunk = GST_MEM_CHUNK_LINK (mem);
|
|
||||||
|
|
||||||
#ifdef HAVE_I386
|
|
||||||
__asm__ __volatile__ ("1: \t"
|
|
||||||
" movl %2, (%1) \n"
|
|
||||||
CHUNK_LOCK "cmpxchg %1, %0 \n\t"
|
|
||||||
" jnz 1b \n\t"::
|
|
||||||
"m" (*mem_chunk), "r" (chunk), "a" (mem_chunk->free));
|
|
||||||
#else
|
|
||||||
fprintf (stderr, "This only compiles correctly on i386. Sorry\n");
|
|
||||||
abort ();
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
|
|
||||||
typedef struct _GstMemChunk GstMemChunk;
|
|
||||||
typedef struct _GstMemChunkElement GstMemChunkElement;
|
|
||||||
|
|
||||||
struct _GstMemChunkElement
|
|
||||||
{
|
|
||||||
GstMemChunkElement *link; /* next cell in the lifo */
|
|
||||||
GstMemChunkElement *area;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstMemChunk
|
|
||||||
{
|
|
||||||
volatile GstMemChunkElement *free; /* the first free element */
|
|
||||||
volatile gulong cnt; /* used to avoid ABA problem */
|
|
||||||
|
|
||||||
gchar *name;
|
|
||||||
gulong area_size;
|
|
||||||
gulong chunk_size;
|
|
||||||
gulong atom_size;
|
|
||||||
gboolean cleanup;
|
|
||||||
};
|
|
||||||
|
|
||||||
GstMemChunk* gst_mem_chunk_new (gchar *name,
|
|
||||||
gint atom_size,
|
|
||||||
gulong area_size,
|
|
||||||
gint type);
|
|
||||||
|
|
||||||
void gst_mem_chunk_destroy (GstMemChunk *mem_chunk);
|
|
||||||
|
|
||||||
gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk);
|
|
||||||
void gst_mem_chunk_free (GstMemChunk *mem_chunk,
|
|
||||||
gpointer mem);
|
|
|
@ -1,85 +0,0 @@
|
||||||
#include <string.h> /* strerror */
|
|
||||||
#include <stdlib.h> /* strerror */
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include "gstmemchunk.h"
|
|
||||||
|
|
||||||
#define MAX_THREADS 100
|
|
||||||
|
|
||||||
static GstMemChunk *_chunks;
|
|
||||||
|
|
||||||
static gint num_allocs;
|
|
||||||
static gint num_threads;
|
|
||||||
|
|
||||||
static gpointer
|
|
||||||
alloc_chunk (void)
|
|
||||||
{
|
|
||||||
gpointer ret;
|
|
||||||
|
|
||||||
ret = gst_mem_chunk_alloc (_chunks);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_chunk (gpointer chunk)
|
|
||||||
{
|
|
||||||
gst_mem_chunk_free (_chunks, chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
run_test (void *threadid)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
gpointer chunk;
|
|
||||||
|
|
||||||
g_usleep (G_USEC_PER_SEC);
|
|
||||||
|
|
||||||
for (i = 0; i < num_allocs; i++) {
|
|
||||||
chunk = alloc_chunk ();
|
|
||||||
free_chunk (chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_thread_exit (NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gint
|
|
||||||
main (gint argc, gchar * argv[])
|
|
||||||
{
|
|
||||||
GThread *threads[MAX_THREADS];
|
|
||||||
GError *error;
|
|
||||||
int t;
|
|
||||||
|
|
||||||
gst_init (&argc, &argv);
|
|
||||||
|
|
||||||
if (argc != 3) {
|
|
||||||
g_print ("usage: %s <num_threads> <num_allocs>\n", argv[0]);
|
|
||||||
exit (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
num_threads = atoi (argv[1]);
|
|
||||||
num_allocs = atoi (argv[2]);
|
|
||||||
|
|
||||||
_chunks = gst_mem_chunk_new ("test", 32, 32 * 16, G_ALLOC_AND_FREE);
|
|
||||||
|
|
||||||
for (t = 0; t < num_threads; t++) {
|
|
||||||
error = NULL;
|
|
||||||
threads[t] = g_thread_create (run_test, GINT_TO_POINTER (t), TRUE, &error);
|
|
||||||
if (error) {
|
|
||||||
printf ("ERROR: g_thread_create() %s\n", error->message);
|
|
||||||
exit (-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf ("main(): Created %d threads.\n", t);
|
|
||||||
|
|
||||||
for (t = 0; t < num_threads; t++) {
|
|
||||||
g_thread_join (threads[t]);
|
|
||||||
}
|
|
||||||
g_mem_chunk_info ();
|
|
||||||
|
|
||||||
gst_mem_chunk_destroy (_chunks);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in a new issue