os/ossrv/genericopenlibs/liboil/src/liboilfunction.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
 * LIBOIL - Library of Optimized Inner Loops
sl@0
     3
 * Copyright (c) 2003,2004 David A. Schleef <ds@schleef.org>
sl@0
     4
 * All rights reserved.
sl@0
     5
 *
sl@0
     6
 * Redistribution and use in source and binary forms, with or without
sl@0
     7
 * modification, are permitted provided that the following conditions
sl@0
     8
 * are met:
sl@0
     9
 * 1. Redistributions of source code must retain the above copyright
sl@0
    10
 *    notice, this list of conditions and the following disclaimer.
sl@0
    11
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    12
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    13
 *    documentation and/or other materials provided with the distribution.
sl@0
    14
 * 
sl@0
    15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
sl@0
    16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
sl@0
    17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
sl@0
    19
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
sl@0
    20
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
sl@0
    21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    23
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
sl@0
    24
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
sl@0
    25
 * POSSIBILITY OF SUCH DAMAGE.
sl@0
    26
 */
sl@0
    27
//Portions Copyright (c)  2008-2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
sl@0
    28
sl@0
    29
#ifdef HAVE_CONFIG_H
sl@0
    30
#include "config.h"
sl@0
    31
#endif
sl@0
    32
#include <liboil/liboildebug.h>
sl@0
    33
#include <liboil/liboilcpu.h>
sl@0
    34
#include <liboil/liboilfault.h>
sl@0
    35
#include <liboil/liboiltest.h>
sl@0
    36
sl@0
    37
#include <stdio.h>
sl@0
    38
#include <string.h>
sl@0
    39
#include <stdlib.h>
sl@0
    40
#include <time.h>
sl@0
    41
sl@0
    42
/**
sl@0
    43
 * SECTION:liboilclass-unstable
sl@0
    44
 * @title:OilFunctionClass
sl@0
    45
 * @short_description: Functions for manipulating function classes
sl@0
    46
 *
sl@0
    47
 * <para>
sl@0
    48
 * Functions operate on arrays of data.  The arrays can be either source
sl@0
    49
 * arrays (input only), destination arrays (output only), or in-place
sl@0
    50
 * arrays (both input and output).
sl@0
    51
 * </para>
sl@0
    52
 *
sl@0
    53
 * <para>
sl@0
    54
 * The interpretation of a parameter can usually be determined from its
sl@0
    55
 * name.  Parameters for arrays are of the form d1_1xn, where the first
sl@0
    56
 * character represents the direction (source, destination, or in-place),
sl@0
    57
 * the second represents the index for that particular direction, and
sl@0
    58
 * the characters after the underscore indicate the size of the array.
sl@0
    59
 * In this case, "1xn" represents an array that is 1 by N.  Note that
sl@0
    60
 * the index and the size can both be omitted, giving a default of 1
sl@0
    61
 * for the index and 1xn for the size.
sl@0
    62
 * </para>
sl@0
    63
 *
sl@0
    64
 * <para>
sl@0
    65
 * Parameters that represent strides are of the form "d1s".  The
sl@0
    66
 * interpretation is similar to above, except that the s indicates
sl@0
    67
 * a stride parameter.
sl@0
    68
 * </para>
sl@0
    69
 *
sl@0
    70
 * <para>
sl@0
    71
 * The exceptions to the above rule are "dest", "src", "dstr", "sstr", etc.
sl@0
    72
 * These are aliases for "d1", "s1", "d1s", and "s1s", respectively.  This
sl@0
    73
 * form is deprecated and will be removed in the 0.4 series.
sl@0
    74
 * </para>
sl@0
    75
 *
sl@0
    76
 * <para>
sl@0
    77
 * Two special parameters are "n" and "m", which determine the size of
sl@0
    78
 * the arrays in other parameters.
sl@0
    79
 * </para>
sl@0
    80
 *
sl@0
    81
 * <para>
sl@0
    82
 * Data arrays are laid out such that rows are separated by the number
sl@0
    83
 * of bytes given by the corresponding stride.  Elements in each row
sl@0
    84
 * are contiguous.  If there is no stride parameter corresponding to an
sl@0
    85
 * array, the rows of the array are contiguous.
sl@0
    86
 * </para>
sl@0
    87
 */
sl@0
    88
sl@0
    89
/**
sl@0
    90
 * SECTION:liboilimpl-unstable
sl@0
    91
 * @title:OilFunctionImpl
sl@0
    92
 * @short_description: Functions for manipulating function implementations.
sl@0
    93
 */
sl@0
    94
sl@0
    95
sl@0
    96
#ifndef __SYMBIAN32__
sl@0
    97
extern OilFunctionClass *_oil_function_class_array[];
sl@0
    98
extern OilFunctionImpl *_oil_function_impl_array[];
sl@0
    99
#else
sl@0
   100
extern OilFunctionClass** __oil_function_class_array(void);
sl@0
   101
extern OilFunctionImpl** __oil_function_impl_array(void);
sl@0
   102
#define _oil_function_class_array ((OilFunctionClass **)(__oil_function_class_array()))
sl@0
   103
#define _oil_function_impl_array ((OilFunctionImpl **)(__oil_function_impl_array()))
sl@0
   104
extern void init(void);
sl@0
   105
extern void init_impl(void);
sl@0
   106
#endif
sl@0
   107
sl@0
   108
sl@0
   109
static int _oil_n_function_impls;
sl@0
   110
static int _oil_n_function_classes;
sl@0
   111
sl@0
   112
static void oil_init_pointers (void);
sl@0
   113
static void oil_init_structs (void);
sl@0
   114
sl@0
   115
static char * xstrdup (const char *s);
sl@0
   116
sl@0
   117
void _oil_cpu_init (void);
sl@0
   118
sl@0
   119
/**
sl@0
   120
 * SECTION:liboilinit
sl@0
   121
 * @title: Intialization
sl@0
   122
 * @short_description: Initialization functions
sl@0
   123
 */
sl@0
   124
/**
sl@0
   125
 * SECTION:liboilinit-unstable
sl@0
   126
 * @title: Intialization
sl@0
   127
 * @short_description: Initialization functions
sl@0
   128
 */
sl@0
   129
/**
sl@0
   130
 * oil_init:
sl@0
   131
 *
sl@0
   132
 * Initialize liboil.  This function must be called before any
sl@0
   133
 * other liboil function is used.  oil_init() may be called multiple
sl@0
   134
 * times.
sl@0
   135
 *
sl@0
   136
 * Since: 0.3.0
sl@0
   137
 */
sl@0
   138
static int _oil_inited = 0;
sl@0
   139
sl@0
   140
#ifdef __SYMBIAN32__
sl@0
   141
EXPORT_C
sl@0
   142
#endif
sl@0
   143
void
sl@0
   144
oil_init (void)
sl@0
   145
{
sl@0
   146
sl@0
   147
  if (_oil_inited) return;
sl@0
   148
  _oil_inited = 1;
sl@0
   149
sl@0
   150
	#ifdef	__SYMBIAN32__
sl@0
   151
  init();
sl@0
   152
  init_impl();	
sl@0
   153
  #endif
sl@0
   154
  
sl@0
   155
  srand(time(NULL));
sl@0
   156
sl@0
   157
  _oil_debug_init ();
sl@0
   158
  _oil_cpu_init ();
sl@0
   159
  oil_init_pointers ();
sl@0
   160
  oil_init_structs ();
sl@0
   161
sl@0
   162
  oil_optimize_all ();
sl@0
   163
sl@0
   164
  OIL_INFO ("oil_init() finished");
sl@0
   165
}
sl@0
   166
sl@0
   167
/**
sl@0
   168
 * oil_init_no_optimize:
sl@0
   169
 *
sl@0
   170
 * Initialize liboil similar to oil_init(), but do not run the
sl@0
   171
 * profiling stage.  This function is mainly useful for internal
sl@0
   172
 * programs.
sl@0
   173
 */
sl@0
   174
#ifdef __SYMBIAN32__
sl@0
   175
EXPORT_C
sl@0
   176
#endif
sl@0
   177
void
sl@0
   178
oil_init_no_optimize (void)
sl@0
   179
{
sl@0
   180
  if (_oil_inited) return;
sl@0
   181
  _oil_inited = 1;
sl@0
   182
sl@0
   183
  srand(time(NULL));
sl@0
   184
sl@0
   185
  _oil_debug_init ();
sl@0
   186
  _oil_cpu_init ();
sl@0
   187
  oil_init_pointers ();
sl@0
   188
  oil_init_structs ();
sl@0
   189
}
sl@0
   190
sl@0
   191
/**
sl@0
   192
 * oil_optimize_all:
sl@0
   193
 *
sl@0
   194
 * Optimize all function classes.
sl@0
   195
 */
sl@0
   196
 #ifdef __SYMBIAN32__
sl@0
   197
EXPORT_C 
sl@0
   198
#endif
sl@0
   199
void
sl@0
   200
oil_optimize_all (void)
sl@0
   201
{
sl@0
   202
  OilFunctionClass *klass;
sl@0
   203
  int i;
sl@0
   204
sl@0
   205
  oil_fault_check_enable ();
sl@0
   206
  for (i = 0; i < _oil_n_function_classes; i++) {
sl@0
   207
    klass = oil_class_get_by_index (i);
sl@0
   208
sl@0
   209
    oil_class_optimize (klass);
sl@0
   210
  }
sl@0
   211
  OIL_INFO("%d classes, %d implementations, %d enabled",
sl@0
   212
      _oil_n_function_classes, _oil_n_function_impls, 0);
sl@0
   213
  oil_fault_check_disable ();
sl@0
   214
}
sl@0
   215
sl@0
   216
/**
sl@0
   217
 * oil_optimize:
sl@0
   218
 * @class_name: a string
sl@0
   219
 *
sl@0
   220
 * Optimize the function class that has the name specified by @class_name.
sl@0
   221
 */
sl@0
   222
#ifdef __SYMBIAN32__
sl@0
   223
EXPORT_C 
sl@0
   224
#endif
sl@0
   225
void
sl@0
   226
oil_optimize (const char *class_name)
sl@0
   227
{
sl@0
   228
  OilFunctionClass *klass;
sl@0
   229
sl@0
   230
  klass = oil_class_get (class_name);
sl@0
   231
  if (klass == NULL) {
sl@0
   232
    OIL_ERROR ("could not find class %s", class_name);
sl@0
   233
    return;
sl@0
   234
  }
sl@0
   235
sl@0
   236
  oil_class_optimize (klass);
sl@0
   237
}
sl@0
   238
sl@0
   239
/**
sl@0
   240
 * oil_class_get_n_classes:
sl@0
   241
 *
sl@0
   242
 * Returns the number of function classes.
sl@0
   243
 *
sl@0
   244
 * Returns: the number of function classes
sl@0
   245
 */
sl@0
   246
#ifdef __SYMBIAN32__
sl@0
   247
EXPORT_C
sl@0
   248
#endif
sl@0
   249
int
sl@0
   250
oil_class_get_n_classes (void)
sl@0
   251
{
sl@0
   252
  return _oil_n_function_classes;
sl@0
   253
}
sl@0
   254
sl@0
   255
/**
sl@0
   256
 * oil_class_get_by_index:
sl@0
   257
 * @i: index
sl@0
   258
 *
sl@0
   259
 * Returns a pointer to the function class with index @i.
sl@0
   260
 *
sl@0
   261
 * Returns: an @OilFunctionClass
sl@0
   262
 */
sl@0
   263
 
sl@0
   264
#ifdef __SYMBIAN32__
sl@0
   265
EXPORT_C  
sl@0
   266
#endif
sl@0
   267
OilFunctionClass *
sl@0
   268
oil_class_get_by_index (int i)
sl@0
   269
{
sl@0
   270
  if (i<0 || i>=_oil_n_function_classes) return NULL;
sl@0
   271
sl@0
   272
  return _oil_function_class_array[i];
sl@0
   273
}
sl@0
   274
sl@0
   275
/**
sl@0
   276
 * oil_impl_is_runnable:
sl@0
   277
 * @impl: an @OilFunctionImpl
sl@0
   278
 *
sl@0
   279
 * Determines whether the function implementation given by @impl
sl@0
   280
 * can be executed by the current CPU.
sl@0
   281
 *
sl@0
   282
 * Returns: 1 if the implementation can be executed, otherwise 0
sl@0
   283
 */
sl@0
   284
#ifdef __SYMBIAN32__
sl@0
   285
EXPORT_C  
sl@0
   286
#endif 
sl@0
   287
int
sl@0
   288
oil_impl_is_runnable (OilFunctionImpl *impl)
sl@0
   289
{
sl@0
   290
  unsigned int oil_cpu_flags = oil_cpu_get_flags();
sl@0
   291
sl@0
   292
  if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags))
sl@0
   293
    return 0;
sl@0
   294
  return 1;
sl@0
   295
}
sl@0
   296
sl@0
   297
//#ifdef __SYMBIAN32__
sl@0
   298
//EXPORT_C unsigned long _oil_cpu_flags()
sl@0
   299
	//{
sl@0
   300
	//return &oil_cpu_flags;
sl@0
   301
	//}
sl@0
   302
//#endif
sl@0
   303
sl@0
   304
/**
sl@0
   305
 * oil_impl_is_usable:
sl@0
   306
 * @impl: an @OilFunctionImpl
sl@0
   307
 *
sl@0
   308
 * Determines whether the function implementation given by @impl
sl@0
   309
 * is useful, that is, it can be executed on the current CPU and
sl@0
   310
 * passes tests.
sl@0
   311
 *
sl@0
   312
 * Returns: 1 if the implementation can be used, otherwise 0
sl@0
   313
 */
sl@0
   314
#ifdef __SYMBIAN32__
sl@0
   315
EXPORT_C  
sl@0
   316
#endif
sl@0
   317
int
sl@0
   318
oil_impl_is_usable (OilFunctionImpl *impl)
sl@0
   319
{
sl@0
   320
  unsigned int oil_cpu_flags = oil_cpu_get_flags();
sl@0
   321
sl@0
   322
  if ((impl->flags & OIL_CPU_FLAG_MASK) & (~oil_cpu_flags))
sl@0
   323
    return 0;
sl@0
   324
  if (impl->flags & OIL_IMPL_FLAG_DISABLED)
sl@0
   325
    return 0;
sl@0
   326
  return 1;
sl@0
   327
}
sl@0
   328
sl@0
   329
/**
sl@0
   330
 * oil_impl_get_by_index:
sl@0
   331
 * @i: index
sl@0
   332
 *
sl@0
   333
 * Returns a pointer to the function implementation with index @i.
sl@0
   334
 *
sl@0
   335
 * Returns: a pointer to a function implementation structure
sl@0
   336
 */
sl@0
   337
#ifdef __SYMBIAN32__
sl@0
   338
EXPORT_C  
sl@0
   339
#endif 
sl@0
   340
OilFunctionImpl *
sl@0
   341
oil_impl_get_by_index (int i)
sl@0
   342
{
sl@0
   343
  if (i<0 || i>=_oil_n_function_impls) return NULL;
sl@0
   344
sl@0
   345
  return _oil_function_impl_array[i];
sl@0
   346
}
sl@0
   347
sl@0
   348
/**
sl@0
   349
 * oil_class_get:
sl@0
   350
 * @class_name: the name of the function class
sl@0
   351
 *
sl@0
   352
 * Returns a pointer to the function class that has the given class
sl@0
   353
 * name.  If no such class is found, NULL is returned.
sl@0
   354
 *
sl@0
   355
 * Returns: a pointer to a function class
sl@0
   356
 */
sl@0
   357
#ifdef __SYMBIAN32__
sl@0
   358
EXPORT_C  
sl@0
   359
#endif
sl@0
   360
OilFunctionClass *
sl@0
   361
oil_class_get (const char *class_name)
sl@0
   362
{
sl@0
   363
  OilFunctionClass *klass;
sl@0
   364
  int i;
sl@0
   365
sl@0
   366
  for (i = 0; i < _oil_n_function_classes; i++) {
sl@0
   367
    klass = oil_class_get_by_index (i);
sl@0
   368
sl@0
   369
    if (strcmp (klass->name, class_name) == 0)
sl@0
   370
      return klass;
sl@0
   371
  }
sl@0
   372
  return NULL;
sl@0
   373
}
sl@0
   374
sl@0
   375
/**
sl@0
   376
 * oil_class_choose_by_name:
sl@0
   377
 * @klass: a function class
sl@0
   378
 * @name: the name of an implementation
sl@0
   379
 *
sl@0
   380
 * Sets the chosen implementation for the given function class to
sl@0
   381
 * the implementation with the given name.  If no implementation
sl@0
   382
 * having the given name is found, the chosen implementation is
sl@0
   383
 * not changed.
sl@0
   384
 */
sl@0
   385
 #ifdef __SYMBIAN32__
sl@0
   386
EXPORT_C 
sl@0
   387
#endif
sl@0
   388
void
sl@0
   389
oil_class_choose_by_name (OilFunctionClass * klass, const char *name)
sl@0
   390
{
sl@0
   391
  OilFunctionImpl *impl;
sl@0
   392
sl@0
   393
  for(impl = klass->first_impl; impl; impl = impl->next) {
sl@0
   394
    if (impl->name && strcmp (impl->name, name) == 0) {
sl@0
   395
      klass->chosen_impl = impl;
sl@0
   396
      klass->func = impl->func;
sl@0
   397
      return;
sl@0
   398
    }
sl@0
   399
  }
sl@0
   400
}
sl@0
   401
sl@0
   402
/**
sl@0
   403
 * oil_class_optimize:
sl@0
   404
 * @klass: a function class
sl@0
   405
 *
sl@0
   406
 * Tests and profiles each implementation for the given function
sl@0
   407
 * class.  Testing compares the output of running each implementation
sl@0
   408
 * on random input against the reference implementation for the
sl@0
   409
 * same input.
sl@0
   410
 */
sl@0
   411
#ifdef __SYMBIAN32__
sl@0
   412
EXPORT_C  
sl@0
   413
#endif
sl@0
   414
void
sl@0
   415
oil_class_optimize (OilFunctionClass * klass)
sl@0
   416
{
sl@0
   417
  OilFunctionImpl *impl;
sl@0
   418
  OilFunctionImpl *min_impl;
sl@0
   419
  OilTest *test;
sl@0
   420
  int ret;
sl@0
   421
sl@0
   422
  OIL_DEBUG ("optimizing class %s", klass->name);
sl@0
   423
sl@0
   424
  if (klass->reference_impl == NULL) {
sl@0
   425
    OIL_ERROR ("class %s has no reference implmentation", klass->name);
sl@0
   426
    return;
sl@0
   427
  }
sl@0
   428
  if (klass->first_impl == NULL) {
sl@0
   429
    OIL_ERROR ("class %s has no implmentations", klass->name);
sl@0
   430
    return;
sl@0
   431
  }
sl@0
   432
sl@0
   433
  test = oil_test_new (klass);
sl@0
   434
  if (test == NULL) {
sl@0
   435
    OIL_ERROR ("failed to test function class %s", klass->name);
sl@0
   436
    return;
sl@0
   437
  }
sl@0
   438
sl@0
   439
  min_impl = NULL;
sl@0
   440
  for (impl = klass->first_impl; impl; impl = impl->next) {
sl@0
   441
    OIL_LOG ("testing impl %s", impl->name);
sl@0
   442
    if (!oil_impl_is_runnable (impl))
sl@0
   443
      continue;
sl@0
   444
sl@0
   445
    ret = oil_test_check_impl (test, impl);
sl@0
   446
    if (ret) {
sl@0
   447
      impl->profile_ave = test->profile_ave;
sl@0
   448
      impl->profile_std = test->profile_std;
sl@0
   449
      OIL_LOG ("impl %s ave=%g std=%g", impl->name, impl->profile_ave,
sl@0
   450
          impl->profile_std);
sl@0
   451
      if (min_impl == NULL) {
sl@0
   452
        min_impl = impl;
sl@0
   453
      } else {
sl@0
   454
        if (impl->profile_ave < min_impl->profile_ave) {
sl@0
   455
          min_impl = impl;
sl@0
   456
        }
sl@0
   457
      }
sl@0
   458
    } else {
sl@0
   459
      OIL_WARNING("disabling implementation %s", impl->name);
sl@0
   460
      impl->profile_ave = test->profile_ave;
sl@0
   461
      impl->profile_std = test->profile_std;
sl@0
   462
      impl->flags |= OIL_IMPL_FLAG_DISABLED;
sl@0
   463
    }
sl@0
   464
  }
sl@0
   465
  if (min_impl == NULL) {
sl@0
   466
    OIL_ERROR ("failed to find optimal implementation for class %s",
sl@0
   467
        klass->name);
sl@0
   468
    return;
sl@0
   469
  }
sl@0
   470
sl@0
   471
  OIL_DEBUG("choosing implementation %s", min_impl->name);
sl@0
   472
  klass->chosen_impl = min_impl;
sl@0
   473
  klass->func = min_impl->func;
sl@0
   474
sl@0
   475
  oil_test_free (test);
sl@0
   476
}
sl@0
   477
sl@0
   478
static void
sl@0
   479
oil_init_pointers (void)
sl@0
   480
{
sl@0
   481
  int i;
sl@0
   482
sl@0
   483
  for(i=0;_oil_function_class_array[i];i++) {
sl@0
   484
    _oil_n_function_classes++;
sl@0
   485
  }
sl@0
   486
sl@0
   487
  for(i=0;_oil_function_impl_array[i];i++) {
sl@0
   488
    _oil_n_function_impls++;
sl@0
   489
  }
sl@0
   490
sl@0
   491
}
sl@0
   492
sl@0
   493
static void
sl@0
   494
oil_init_structs (void)
sl@0
   495
{
sl@0
   496
  int i;
sl@0
   497
  OilFunctionImpl *impl;
sl@0
   498
sl@0
   499
  for (i = 0; i < _oil_n_function_impls; i++) {
sl@0
   500
    impl = oil_impl_get_by_index (i);
sl@0
   501
    OIL_LOG ("registering impl %p (%s)", impl,
sl@0
   502
          (impl->name != NULL) ? impl->name : "NULL");
sl@0
   503
    if (impl->klass == NULL) {
sl@0
   504
      OIL_ERROR ("impl->klass is NULL for impl %p (%s)", impl,
sl@0
   505
          (impl->name != NULL) ? impl->name : "NULL");
sl@0
   506
      continue;
sl@0
   507
    }
sl@0
   508
    impl->next = impl->klass->first_impl;
sl@0
   509
    impl->klass->first_impl = impl;
sl@0
   510
    if (impl->flags & OIL_IMPL_FLAG_REF) {
sl@0
   511
      impl->klass->reference_impl = impl;
sl@0
   512
      impl->klass->chosen_impl = impl;
sl@0
   513
      impl->klass->func = impl->func;
sl@0
   514
    }
sl@0
   515
  }
sl@0
   516
}
sl@0
   517
sl@0
   518
/**
sl@0
   519
 * oil_class_register_impl_by_name:
sl@0
   520
 * @klass_name: the name of the class
sl@0
   521
 * @impl: an implementation
sl@0
   522
 *
sl@0
   523
 * Adds @impl to the list of implementations associated with
sl@0
   524
 * the function class given by @klass_name.
sl@0
   525
 */
sl@0
   526
 #ifdef __SYMBIAN32__
sl@0
   527
EXPORT_C
sl@0
   528
#endif
sl@0
   529
void
sl@0
   530
oil_class_register_impl_by_name (const char *klass_name, OilFunctionImpl *impl)
sl@0
   531
{
sl@0
   532
  OilFunctionClass *klass;
sl@0
   533
sl@0
   534
  klass = oil_class_get (klass_name);
sl@0
   535
  if (klass == NULL) return;
sl@0
   536
sl@0
   537
  oil_class_register_impl (klass, impl);
sl@0
   538
}
sl@0
   539
sl@0
   540
/**
sl@0
   541
 * oil_class_register_impl:
sl@0
   542
 * @klass: the class
sl@0
   543
 * @impl: an implementation
sl@0
   544
 *
sl@0
   545
 * Adds @impl to the list of implementations associated with
sl@0
   546
 * the function class given by @klass.
sl@0
   547
 */
sl@0
   548
 #ifdef __SYMBIAN32__
sl@0
   549
EXPORT_C
sl@0
   550
#endif
sl@0
   551
void
sl@0
   552
oil_class_register_impl (OilFunctionClass *klass, OilFunctionImpl *impl)
sl@0
   553
{
sl@0
   554
  impl->klass = klass;
sl@0
   555
  impl->next = impl->klass->first_impl;
sl@0
   556
  klass->first_impl = impl;
sl@0
   557
  if (impl->flags & OIL_IMPL_FLAG_REF) {
sl@0
   558
    impl->klass->reference_impl = impl;
sl@0
   559
    impl->klass->chosen_impl = impl;
sl@0
   560
    impl->klass->func = impl->func;
sl@0
   561
  }
sl@0
   562
}
sl@0
   563
sl@0
   564
/**
sl@0
   565
 * oil_class_register_impl_full:
sl@0
   566
 * @klass: the class
sl@0
   567
 * @func: the function
sl@0
   568
 * @name: name of the function
sl@0
   569
 * @flags: CPU flags
sl@0
   570
 *
sl@0
   571
 * Adds @func to the list of implementations associated with
sl@0
   572
 * the function class given by @klass.
sl@0
   573
 */
sl@0
   574
 #ifdef __SYMBIAN32__
sl@0
   575
EXPORT_C  
sl@0
   576
#endif
sl@0
   577
void
sl@0
   578
oil_class_register_impl_full (OilFunctionClass *klass,
sl@0
   579
    void (*func)(void), const char *name, unsigned int flags)
sl@0
   580
{
sl@0
   581
  OilFunctionImpl *impl;
sl@0
   582
sl@0
   583
  impl = malloc(sizeof(OilFunctionImpl));
sl@0
   584
  memset (impl, 0, sizeof(OilFunctionImpl));
sl@0
   585
sl@0
   586
  impl->func = (void*)func;
sl@0
   587
  impl->flags = flags;
sl@0
   588
  impl->name = xstrdup(name);
sl@0
   589
sl@0
   590
  oil_class_register_impl(klass,impl);
sl@0
   591
}
sl@0
   592
sl@0
   593
static char *
sl@0
   594
xstrdup (const char *s)
sl@0
   595
{
sl@0
   596
  int n = strlen(s);
sl@0
   597
  char *t;
sl@0
   598
sl@0
   599
  n = strlen(s);
sl@0
   600
  t = malloc(n + 1);
sl@0
   601
  memcpy (t, s, n);
sl@0
   602
  t[n] = 0;
sl@0
   603
sl@0
   604
  return t;
sl@0
   605
}
sl@0
   606