Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id ; Tue, 28 Jan 2003 12:43:53 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id ; Tue, 28 Jan 2003 12:43:53 -0500 Received: from amsfep12-int.chello.nl ([213.46.243.18]:19781 "EHLO amsfep12-int.chello.nl") by vger.kernel.org with ESMTP id ; Tue, 28 Jan 2003 12:43:33 -0500 Subject: Permission to use atomic code under LGPL From: Christian Fredrik Kalager Schaller To: linux-kernel@vger.kernel.org Content-Type: multipart/mixed; boundary="=-sZrg2mRLgCtwubZJ8Z2K" Organization: Message-Id: <1043776362.2939.14.camel@thebox> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.2.1 (1.2.1-4) Date: 28 Jan 2003 18:52:42 +0100 Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org --=-sZrg2mRLgCtwubZJ8Z2K Content-Type: text/plain Content-Transfer-Encoding: 7bit Hi, I am with the GStreamer project (www.gstreamer.net). We did a small license audit the other day and discovered we included some code from the kernel. GStreamer uses the LGPL so this is a problem for us. The code in question is the atomic code and is included in our sourcefile below. Do the person(s) in question responsible for this code mind if we re-license it under the LGPL? We will of course add comments in the code stating its origin with copyrights etc. I am not subscribed to the list so if anyone has objections to this relicensing of this particular piece of code, please CC me any responses. Sincerely, Christian -- Christian Fredrik Kalager Schaller --=-sZrg2mRLgCtwubZJ8Z2K Content-Disposition: attachment; filename=gstatomic_impl.h Content-Type: text/x-c-header; name=gstatomic_impl.h; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit /* GStreamer * Copyright (C) <1999> Erik Walthinsen * * 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. */ #ifndef __GST_ATOMIC_IMPL_H__ #define __GST_ATOMIC_IMPL_H__ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "gstatomic.h" #include "gstmacros.h" G_BEGIN_DECLS #if defined (GST_CAN_INLINE) || defined (__GST_ATOMIC_C__) /***** Intel x86 *****/ #if defined (HAVE_CPU_I386) && defined(__GNUC__) #ifdef GST_CONFIG_NO_SMP #define SMP_LOCK "" #else #define SMP_LOCK "lock ; " #endif GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; } GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { __asm__ __volatile__( SMP_LOCK "addl %1,%0" :"=m" (aint->counter) :"ir" (val), "m" (aint->counter)); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { __asm__ __volatile__( SMP_LOCK "incl %0" :"=m" (aint->counter) :"m" (aint->counter)); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { guchar res; __asm__ __volatile__( SMP_LOCK "decl %0; sete %1" :"=m" (aint->counter), "=qm" (res) :"m" (aint->counter) : "memory"); return res != 0; } /***** PowerPC *****/ #elif defined (HAVE_CPU_PPC) && defined(__GNUC__) #ifdef GST_CONFIG_NO_SMP #define SMP_SYNC "" #define SMP_ISYNC #else #define SMP_SYNC "sync" #define SMP_ISYNC "\n\tisync" #endif /* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx. * The old ATOMIC_SYNC_FIX covered some but not all of this. */ #ifdef GST_CONFIG_IBM405_ERR77 #define PPC405_ERR77(ra,rb) "dcbt " #ra "," #rb ";" #else #define PPC405_ERR77(ra,rb) #endif GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; } GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { int t; __asm__ __volatile__( "1: lwarx %0,0,%3 # atomic_add\n\ add %0,%2,%0\n" PPC405_ERR77(0,%3) " stwcx. %0,0,%3 \n\ bne- 1b" : "=&r" (t), "=m" (aint->counter) : "r" (val), "r" (&aint->counter), "m" (aint->counter) : "cc"); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { int t; __asm__ __volatile__( "1: lwarx %0,0,%2 # atomic_inc\n\ addic %0,%0,1\n" PPC405_ERR77(0,%2) " stwcx. %0,0,%2 \n\ bne- 1b" : "=&r" (t), "=m" (aint->counter) : "r" (&aint->counter), "m" (aint->counter) : "cc"); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { int t; __asm__ __volatile__( "1: lwarx %0,0,%1 # atomic_dec_return\n\ addic %0,%0,-1\n" PPC405_ERR77(0,%1) " stwcx. %0,0,%1\n\ bne- 1b" SMP_ISYNC : "=&r" (t) : "r" (&aint->counter) : "cc", "memory"); return t == 0; } /***** DEC[/Compaq/HP?/Intel?] Alpha *****/ #elif defined(HAVE_CPU_ALPHA) && defined(__GNUC__) GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; } GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { unsigned long temp; __asm__ __volatile__( "1: ldl_l %0,%1\n" " addl %0,%2,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" ".subsection 2\n" "2: br 1b\n" ".previous" :"=&r" (temp), "=m" (aint->counter) :"Ir" (val), "m" (aint->counter)); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { gst_atomic_int_add (aint, 1); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { long temp, result; int val = 1; __asm__ __volatile__( "1: ldl_l %0,%1\n" " subl %0,%3,%2\n" " subl %0,%3,%0\n" " stl_c %0,%1\n" " beq %0,2f\n" " mb\n" ".subsection 2\n" "2: br 1b\n" ".previous" :"=&r" (temp), "=m" (aint->counter), "=&r" (result) :"Ir" (val), "m" (aint->counter) : "memory"); return result == 0; } /***** Sun SPARC *****/ #elif defined(HAVE_CPU_SPARC) && defined(__GNUC__) GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { } #ifdef GST_CONFIG_NO_SMP GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; } #else GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = (val<<8); } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = (val<<8); } /* * For SMP the trick is you embed the spin lock byte within * the word, use the low byte so signedness is easily retained * via a quick arithmetic shift. It looks like this: * * ---------------------------------------- * | signed 24-bit counter value | lock | atomic_t * ---------------------------------------- * 31 8 7 0 */ GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { int ret = aint->counter; while (ret & 0xff) ret = aint->counter; return ret >> 8; } #endif /* GST_CONFIG_NO_SMP */ GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { register volatile int *ptr asm ("g1"); register int increment asm ("g2"); ptr = &aint->counter; increment = val; __asm__ __volatile__( "mov %%o7, %%g4\n\t" "call ___atomic_add\n\t" " add %%o7, 8, %%o7\n" : "=&r" (increment) : "0" (increment), "r" (ptr) : "g3", "g4", "g7", "memory", "cc"); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { gst_atomic_int_add (aint, 1); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { register volatile int *ptr asm ("g1"); register int increment asm ("g2"); ptr = &aint->counter; increment = val; __asm__ __volatile__( "mov %%o7, %%g4\n\t" "call ___atomic_sub\n\t" " add %%o7, 8, %%o7\n" : "=&r" (increment) : "0" (increment), "r" (ptr) : "g3", "g4", "g7", "memory", "cc"); return increment == 0; } /***** MIPS *****/ #elif defined(HAVE_CPU_MIPS) && defined(__GNUC__) GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; } /* this only works on MIPS II and better */ GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { unsigned long temp; __asm__ __volatile__( "1: ll %0, %1 # atomic_add\n" " addu %0, %2 \n" " sc %0, %1 \n" " beqz %0, 1b \n" : "=&r" (temp), "=m" (aint->counter) : "Ir" (val), "m" (aint->counter)); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { gst_atomic_int_add (aint, 1); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { unsigned long temp, result; int val = 1; __asm__ __volatile__( ".set push \n" ".set noreorder # atomic_sub_return\n" "1: ll %1, %2 \n" " subu %0, %1, %3 \n" " sc %0, %2 \n" " beqz %0, 1b \n" " subu %0, %1, %3 \n" ".set pop \n" : "=&r" (result), "=&r" (temp), "=m" (aint->counter) : "Ir" (val), "m" (aint->counter) : "memory"); return result == 0; } /***** S/390 *****/ #elif defined(HAVE_CPU_S390) && defined(__GNUC__) GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { aint->counter = val; } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { return aint->counter; } #define __CS_LOOP(old_val, new_val, ptr, op_val, op_string) \ __asm__ __volatile__(" l %0,0(%3)\n" \ "0: lr %1,%0\n" \ op_string " %1,%4\n" \ " cs %0,%1,0(%3)\n" \ " jl 0b" \ : "=&d" (old_val), "=&d" (new_val), \ "+m" (((atomic_t *)(ptr))->counter) \ : "a" (ptr), "d" (op_val) : "cc" ); GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { int old_val, new_val; __CS_LOOP(old_val, new_val, aint, val, "ar"); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { int old_val, new_val; __CS_LOOP(old_val, new_val, aint, 1, "ar"); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { int old_val, new_val; __CS_LOOP(old_val, new_val, aint, 1, "sr"); return new_val == 0; } #else #warning consider putting your architecture specific atomic implementations here /* * generic implementation */ GST_INLINE_FUNC void gst_atomic_int_init (GstAtomicInt *aint, gint val) { aint->counter = val; aint->lock = g_mutex_new (); } GST_INLINE_FUNC void gst_atomic_int_destroy (GstAtomicInt *aint) { g_mutex_free (aint->lock); } GST_INLINE_FUNC void gst_atomic_int_set (GstAtomicInt *aint, gint val) { g_mutex_lock (aint->lock); aint->counter = val; g_mutex_unlock (aint->lock); } GST_INLINE_FUNC gint gst_atomic_int_read (GstAtomicInt *aint) { gint res; g_mutex_lock (aint->lock); res = aint->counter; g_mutex_unlock (aint->lock); return res; } GST_INLINE_FUNC void gst_atomic_int_add (GstAtomicInt *aint, gint val) { g_mutex_lock (aint->lock); aint->counter += val; g_mutex_unlock (aint->lock); } GST_INLINE_FUNC void gst_atomic_int_inc (GstAtomicInt *aint) { g_mutex_lock (aint->lock); aint->counter++; g_mutex_unlock (aint->lock); } GST_INLINE_FUNC gboolean gst_atomic_int_dec_and_test (GstAtomicInt *aint) { gboolean res; g_mutex_lock (aint->lock); aint->counter--; res = (aint->counter == 0); g_mutex_unlock (aint->lock); return res; } #endif /* * common functions */ GST_INLINE_FUNC GstAtomicInt* gst_atomic_int_new (gint val) { GstAtomicInt *aint; aint = g_new0 (GstAtomicInt, 1); gst_atomic_int_init (aint, val); return aint; } GST_INLINE_FUNC void gst_atomic_int_free (GstAtomicInt *aint) { gst_atomic_int_destroy (aint); g_free (aint); } #endif /* defined (GST_CAN_INLINE) || defined (__GST_TRASH_STACK_C__)*/ G_END_DECLS #endif /* __GST_ATOMIC_IMPL_H__ */ --=-sZrg2mRLgCtwubZJ8Z2K-- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/