source: trunk/third/gstreamer/gst/gsttrashstack.h @ 21005

Revision 21005, 5.3 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21004, which included commits to RCS files with non-trunk default branches.
Line 
1/* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20#ifndef __GST_TRASH_STACK_H__
21#define __GST_TRASH_STACK_H__
22
23#include <glib.h>
24#include "gstmacros.h"
25
26G_BEGIN_DECLS
27
28typedef struct _GstTrashStack GstTrashStack;
29typedef struct _GstTrashStackElement GstTrashStackElement;
30
31struct _GstTrashStackElement {
32  GstTrashStackElement *next;
33};
34
35typedef volatile gpointer gst_vgpointer;/* gtk-doc volatile workaround */
36typedef volatile gulong gst_vgulong;    /* gtk-doc volatile workaround */
37                                                                               
38struct _GstTrashStack {
39  gst_vgpointer         head; 
40  gst_vgulong           count;          /* for the ABA problem */
41  GMutex                *lock;          /* lock for C fallback */
42};
43
44GST_INLINE_FUNC GstTrashStack*  gst_trash_stack_new     (void);
45GST_INLINE_FUNC void            gst_trash_stack_init    (GstTrashStack *stack);
46GST_INLINE_FUNC void            gst_trash_stack_destroy (GstTrashStack *stack);
47GST_INLINE_FUNC void            gst_trash_stack_free    (GstTrashStack *stack);
48
49GST_INLINE_FUNC void            gst_trash_stack_push    (GstTrashStack *stack, gpointer mem);
50GST_INLINE_FUNC gpointer        gst_trash_stack_pop     (GstTrashStack *stack);
51
52#if defined (GST_CAN_INLINE) || defined (__GST_TRASH_STACK_C__)
53
54#if defined (USE_FAST_STACK_TRASH) && defined (__i386__) && defined (__GNUC__) && __GNUC__ >= 2
55
56#ifdef GST_CONFIG_NO_SMP
57#define SMP_LOCK ""
58#else
59#define SMP_LOCK "lock ; "
60#endif
61
62/*
63 * intel ia32 optimized lockfree implementations
64 */
65GST_INLINE_FUNC void
66gst_trash_stack_init (GstTrashStack *stack)
67{
68  stack->head = NULL;
69  stack->count = 0;
70}
71
72GST_INLINE_FUNC void
73gst_trash_stack_destroy (GstTrashStack *stack)
74{
75}
76
77GST_INLINE_FUNC void
78gst_trash_stack_push (GstTrashStack *stack, gpointer mem)
79{
80 __asm__ __volatile__ (
81   "1:                         \n\t"
82   "  movl %2, (%1);           \n\t"    /* mem->next == stack->head */
83   SMP_LOCK "cmpxchg %1, %0;   \n\t"    /* if head unchanged, move mem into it */
84   "  jnz 1b;                  \n"      /* head changed, retry */
85     :
86     : "m" (*stack),
87       "r" (mem),
88       "a" (stack->head)
89  );
90}
91
92GST_INLINE_FUNC gpointer
93gst_trash_stack_pop (GstTrashStack *stack)
94{
95  GstTrashStackElement *head;
96
97  /* pop is a little more complicated as we need to avoid the so called ABA
98   * problem that arises when a pop and push of the same element happens
99   * right between when we read head->next and try to swing the new pointer
100   * into place. This is usually solved using a counter which makes it highly
101   * inlikely that we manage to grab the wrong head->next value.
102   */
103  __asm__ __volatile__ (
104    "  pushl %%ebx;             \n\t"
105    "  testl %%eax, %%eax;      \n\t"   /* if (head == NULL) return */
106    "  jz 20f;                  \n\t"
107    "10:                        \n\t"
108    "  movl (%%eax), %%ebx;     \n\t"   /* take value pointed to by head (head->next) */
109    "  movl %%edx, %%ecx;       \n\t"   /* take counter */
110    "  incl %%ecx;              \n\t"   /* and increment */
111    SMP_LOCK "cmpxchg8b %1;     \n\t"   /* if eax:edx == *stack, move ebx:ecx to *stack,
112                                         * else *stack is moved into eax:edx again... */
113    "  jnz 10b;                 \n\t"   /* ... and we retry */
114    "20:                        \n\t"
115    "  popl %%ebx               \n"
116      : "=a" (head)
117      :  "m" (*stack),
118         "a" (stack->head),
119         "d" (stack->count)
120      :  "ecx"
121  );
122
123  return head;
124}
125
126#else
127
128/*
129 * generic implementation
130 */
131GST_INLINE_FUNC void
132gst_trash_stack_init (GstTrashStack *stack)
133{
134  stack->head = NULL;
135  stack->lock = g_mutex_new();
136}
137
138GST_INLINE_FUNC void
139gst_trash_stack_destroy (GstTrashStack *stack)
140{
141  g_mutex_free (stack->lock);
142}
143
144GST_INLINE_FUNC void
145gst_trash_stack_push (GstTrashStack *stack, gpointer mem)
146{
147  GstTrashStackElement *elem = (GstTrashStackElement *) mem;
148
149  g_mutex_lock (stack->lock);
150  elem->next = stack->head;
151  stack->head = elem;
152  g_mutex_unlock (stack->lock);
153}
154
155GST_INLINE_FUNC gpointer
156gst_trash_stack_pop (GstTrashStack *stack)
157{
158  GstTrashStackElement *head;
159 
160  g_mutex_lock (stack->lock);
161  head = (GstTrashStackElement *) stack->head;
162  if (head)
163    stack->head = head->next;
164  g_mutex_unlock (stack->lock);
165
166  return head;
167}
168
169#endif
170
171/*
172 * common functions
173 */
174GST_INLINE_FUNC GstTrashStack*
175gst_trash_stack_new (void)
176{
177  GstTrashStack *stack;
178
179  stack = g_new (GstTrashStack, 1);
180  gst_trash_stack_init (stack);
181
182  return stack;
183}
184
185GST_INLINE_FUNC void
186gst_trash_stack_free (GstTrashStack *stack)
187{
188  gst_trash_stack_destroy (stack);
189  g_free (stack);
190}
191
192#endif /* defined (GST_CAN_INLINE) || defined (__GST_TRASH_STACK_C__)*/
193
194G_END_DECLS
195
196#endif /*  __GST_TRASH_STACK_H__ */
Note: See TracBrowser for help on using the repository browser.