source: roaraudio/libroar/roardl.c @ 5503:15152f742401

Last change on this file since 5503:15152f742401 was 5503:15152f742401, checked in by phi, 12 years ago

disallow running appsched's _init() and _free() multiple or other members in wrong order

File size: 22.4 KB
RevLine 
[3297]1//roardl.c:
2
3/*
[5381]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010-2012
[3297]5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
[3517]21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
[3297]23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
[5427]38#ifdef ROAR_HAVE_H_DIRENT
39#include <dirent.h>
40#endif
41
[3367]42#if defined(ROAR_HAVE_LIBDL) && !defined(RTLD_NEXT)
43#define RTLD_NEXT ((void *) -1L)
44#endif
45
[5503]46#define RTF_RA_INITED       0x0001
47#define RTF_APPSCHED_INITED 0x0002
48#define RTF_APPSCHED_FREED  0x0004
49
[5275]50struct roar_dl_lhandle {
[5317]51 size_t refc; // currently unused.
52 int flags;
53 char * libname; // only used for ROAR_DL_FLAG_STATIC.
[5275]54 struct roar_dl_librarypara * para;
55 struct roar_dl_libraryinst * lib;
[5312]56 struct {
57  struct roar_error_state error_state;
58  void *  global_data;
59  void *  global_data_state;
[5317]60  struct roar_notify_core * notifycore;
[5312]61 } context;
[5503]62 unsigned int runtime_flags;
[5275]63#if defined(ROAR_HAVE_LIBDL)
64 void * handle;
[5481]65#elif defined(ROAR_TARGET_WIN32)
66 HMODULE handle;
[5275]67#endif
68};
69
70
71struct roar_dl_librarypara * roar_dl_para_new(const char * args, void * binargv,
72                                              const char * appname, const char * abiversion) {
73 struct roar_dl_librarypara * ret = roar_mm_malloc(sizeof(struct roar_dl_librarypara));
74 ssize_t argc;
75 int err;
76
77 if ( ret == NULL )
78  return NULL;
79
80 memset(ret, 0, sizeof(struct roar_dl_librarypara));
81
82 ret->version    = ROAR_DL_LIBPARA_VERSION;
83 ret->len        = sizeof(struct roar_dl_librarypara);
84 ret->refc       = 1;
85 ret->argc       = 0;
86 ret->argv       = NULL;
87 ret->args_store = NULL;
88 ret->binargv    = binargv;
89 ret->appname    = appname;
90 ret->abiversion = abiversion;
91
92 if ( args != NULL ) {
93  ret->args_store = roar_mm_strdup(args);
94  if ( ret->args_store == NULL ) {
95   err = roar_error;
96   roar_mm_free(ret);
97   roar_error = err;
98   return NULL;
99  }
100
[5482]101  argc = roar_keyval_split(&(ret->argv), ret->args_store, NULL, NULL, 1);
[5275]102  if ( argc == -1 ) {
103   err = roar_error;
104   roar_mm_free(ret->args_store);
105   roar_mm_free(ret);
106   roar_error = err;
107   return NULL;
108  }
109
110  ret->argc = argc;
111 }
112
113 return ret;
114}
115
116int roar_dl_para_ref                    (struct roar_dl_librarypara * para) {
117 if ( para == NULL ) {
[5438]118  ROAR_DBG("roar_dl_para_ref(para=%p) = -1 // error=FAULT", para);
[5275]119  roar_err_set(ROAR_ERROR_FAULT);
120  return -1;
121 }
122
123 para->refc++;
124
[5438]125 ROAR_DBG("roar_dl_para_ref(para=%p) = 0", para);
[5275]126 return 0;
127}
128
129int roar_dl_para_unref                  (struct roar_dl_librarypara * para) {
130 if ( para == NULL ) {
[5438]131  ROAR_DBG("roar_dl_para_unref(para=%p) = -1 // error=FAULT", para);
[5275]132  roar_err_set(ROAR_ERROR_FAULT);
133  return -1;
134 }
135
136 para->refc--;
137
[5438]138 if ( para->refc ) {
139  ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
[5317]140  return 0;
[5438]141 }
[5317]142
143 if ( para->notifycore != NULL )
144  roar_notify_core_unref(para->notifycore);
145
146 if ( para->args_store != NULL ) {
147  roar_mm_free(para->args_store);
148  roar_mm_free(para->argv);
[5275]149 }
150
[5317]151 roar_mm_free(para);
152
[5438]153 ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
[5275]154 return 0;
155}
156int roar_dl_para_check_version          (struct roar_dl_librarypara * para,
157                                         const char * appname, const char * abiversion) {
158 if ( para == NULL ) {
159  roar_err_set(ROAR_ERROR_FAULT);
160  return -1;
161 }
162
163 // check if both appnames are NULL or non-NULL.
164 if ( (para->appname == NULL && appname != NULL) || (para->appname != NULL && appname == NULL) ) {
[5371]165  roar_err_set(ROAR_ERROR_BADHOST);
[5275]166  return -1;
167 }
168
169 // check if the appname matches if given.
170 if ( para->appname != NULL && !!strcmp(para->appname, appname) ) {
[5371]171  roar_err_set(ROAR_ERROR_BADHOST);
[5275]172  return -1;
173 }
174
175 // check if both ABI versions are NULL or non-NULL.
176 if ( (para->abiversion == NULL && abiversion != NULL) || (para->abiversion != NULL && abiversion == NULL) ) {
177  roar_err_set(ROAR_ERROR_BADVERSION);
178  return -1;
179 }
180
181 // check if the ABI versions matches if given.
182 if ( para->abiversion != NULL && !!strcmp(para->abiversion, abiversion) ) {
183  roar_err_set(ROAR_ERROR_BADVERSION);
184  return -1;
185 }
186
187 return 0;
188}
189
190
[3297]191#if defined(ROAR_HAVE_LIBDL)
192static void * _roardl2ldl (struct roar_dl_lhandle * lhandle) {
[5317]193 ROAR_DBG("_roardl2ldl(lhandle=%p) = ?", lhandle);
194
195 if ( lhandle == ROAR_DL_HANDLE_DEFAULT ) {
196  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_DEFAULT);
[3297]197  return RTLD_DEFAULT;
[5317]198 }
[3297]199
[5317]200 if ( lhandle == ROAR_DL_HANDLE_NEXT ) {
201  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_NEXT);
[3297]202  return RTLD_NEXT;
[5317]203 }
[3297]204
[5317]205 ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)(lhandle->handle));
[3297]206 return lhandle->handle;
207}
[5481]208#elif defined(ROAR_TARGET_WIN32)
209static HMODULE _roardl2winhandle(struct roar_dl_lhandle * lhandle) {
210 if ( (void*)lhandle < (void*)128 ) {
211  return NULL;
212 }
213 return lhandle->handle;
214}
[3297]215#endif
216
[5427]217#ifdef ROAR_HAVE_H_DIRENT
218// pvn = prefix, host vendor, host name
219static struct roar_dl_lhandle * _load_from_path_pvn(const char * name,
220                                                    int flags, int ra_init,
221                                                    struct roar_dl_librarypara * para,
222                                                    const char * prefix,
223                                                    const char * hostvendor,
224                                                    const char * hostname) {
225 struct roar_dl_lhandle * ret = NULL;
226 int i, j;
227 char path[1024];
228 const char * path_format[] = {"%s/%s/%s", "%s/%s/universal", "%s/universal/universal"};
229 DIR * dir;
230 struct dirent * dirent;
231 char file[1024];
232 const char * file_format[] = {"%s/%s/%s", "%s/%s/%s" ROAR_SHARED_SUFFIX, "%s/%s/lib%s" ROAR_SHARED_SUFFIX};
233//  cont->handle[idx] = roar_dl_open(name, ROAR_DL_FLAG_DEFAULTS, 1, para);
234//#vars: $PREFIX_PLUGINS, $hostvendor, $hostname, $name
235//#search order: $PREFIX_PLUGINS/{$hostvendor/{$hostname,universal},universal/universal}/*/{,lib}$name.so
236
237 for (i = 0; i < 3; i++) {
238  snprintf(path, sizeof(path), path_format[i], prefix, hostvendor, hostname);
239  dir = opendir(path);
240  if ( dir == NULL )
241   continue;
242
243  while ((dirent = readdir(dir)) != NULL) {
244   if ( !strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") )
245    continue;
246
247   for (j = 0; j < 3; j++) {
248    snprintf(file, sizeof(file), file_format[j], path, dirent->d_name, name);
249    ret = roar_dl_open(file, flags, ra_init, para);
250    if ( ret != NULL ) {
251     closedir(dir);
252     return ret;
253    }
254   }
255  }
256
257  closedir(dir);
258 }
259
260 return NULL;
261}
262
263static struct roar_dl_lhandle * _load_from_path(const char * name, int flags, int ra_init,
264                                                struct roar_dl_librarypara * para) {
265 struct roar_dl_lhandle * ret = NULL;
266 char * host = NULL;
267 char * hostvendor_buffer = NULL;
268 char * hostvendor = NULL;
269 char * hostname = NULL;
270 char * c, * d;
271
272 if ( para != NULL && para->appname != NULL && para->appname[0] != 0 ) {
273  host = roar_mm_strdup(para->appname);
274
275  // if we are out of memory we will likely not pass the rest, so just return in error.
276  if ( host == NULL )
277   return NULL;
278
279  hostname = host;
280  c = strstr(host, "<");
281  if ( c != NULL ) {
282   while (c[-1] == ' ') c--;
283   *c = 0;
284   c++;
285   while (*c == ' ' || *c == '<') c++;
286   if ( *c ) {
287    d = strstr(c, ">");
288    if ( d != NULL )
289     *d = 0;
290
291    d = strstr(c, "/");
292    if ( d != NULL ) {
293     *d = '-';
294     hostvendor = c;
295    } else {
296     hostvendor_buffer = roar_mm_malloc(roar_mm_strlen(c) + 1 /* tailing \0 */ + 6 /* "unreg-" */);
297
298     // see above
299     if ( hostvendor_buffer == NULL ) {
300      roar_mm_free(host);
301      return NULL;
302     }
303
304     strcpy(hostvendor_buffer, "unreg-");
305     strcat(hostvendor_buffer, c);
306     hostvendor = hostvendor_buffer;
307    }
308   }
309  }
310 }
311
312 if ( hostvendor == NULL )
313  hostvendor = "universal";
314
315 if ( hostname == NULL )
316  hostname = "universal";
317
318 ret = _load_from_path_pvn(name, flags, ra_init, para, ROAR_PREFIX_PLUGINS, hostvendor, hostname);
319
320 if ( host != NULL )
321  roar_mm_free(host);
322 if ( hostvendor_buffer != NULL )
323  roar_mm_free(hostvendor_buffer);
324 return ret;
325}
326#endif
327
328static struct roar_dl_lhandle * _roar_dl_open_pluginpath(const char * filename, int flags,
329                                      int ra_init, struct roar_dl_librarypara * para) {
330 flags |= ROAR_DL_FLAG_PLUGINPATH;
331 flags -= ROAR_DL_FLAG_PLUGINPATH;
332
333#ifdef ROAR_HAVE_H_DIRENT
[5430]334 // do normal open for everything with a path name.
335 if ( strstr(filename, "/") != NULL )
336  return roar_dl_open(filename, flags, ra_init, para);
337
[5427]338 return _load_from_path(filename, flags, ra_init, para);
339#else
340 // fall back to system open function.
341 return roar_dl_open(filename, flags, ra_init, para);
342#endif
343}
344
[5275]345struct roar_dl_lhandle * roar_dl_open(const char * filename, int flags,
346                                      int ra_init, struct roar_dl_librarypara * para) {
[3298]347 struct roar_dl_lhandle * ret = NULL;
[5317]348#if defined(ROAR_HAVE_LIBDL)
349#ifdef RTLD_DEEPBIND
[5344]350 int libdl_flags = RTLD_DEEPBIND;
[5317]351#else
[5344]352 int libdl_flags = 0;
[5317]353#endif
354#endif
[5275]355 int err;
[3298]356
[5427]357 switch (flags) {
358  case ROAR_DL_FLAG_DEFAULTS: flags = ROAR_DL_FLAG_NONE;       break;
359  case ROAR_DL_FLAG_PLUGIN:   flags = ROAR_DL_FLAG_PLUGINPATH; break;
360 }
361
362 if ( flags & ROAR_DL_FLAG_PLUGINPATH )
363  return _roar_dl_open_pluginpath(filename, flags, ra_init, para);
[3304]364
[5344]365#if defined(ROAR_HAVE_LIBDL)
366 if ( flags & ROAR_DL_FLAG_LAZY ) {
367  libdl_flags |= RTLD_LAZY;
368 } else {
369  libdl_flags |= RTLD_NOW;
370 }
371#endif
372
[3304]373 if ( (ret = roar_mm_malloc(sizeof(struct roar_dl_lhandle))) == NULL )
374  return NULL;
375
376 memset(ret, 0, sizeof(struct roar_dl_lhandle));
377
[5312]378 roar_err_initstore(&(ret->context.error_state));
379
[5317]380 ret->flags = flags;
[5321]381 ret->refc  = 1;
[3366]382
[5317]383 if ( flags & ROAR_DL_FLAG_STATIC ) {
384  if ( filename == NULL ) {
385   ret->libname = NULL;
386  } else {
387   ret->libname = roar_mm_strdup(filename);
388  }
389 } else {
390#if defined(ROAR_HAVE_LIBDL)
391  ret->handle = dlopen(filename, libdl_flags);
[3304]392
[5317]393  if ( ret->handle == NULL ) {
394   ROAR_DBG("roar_dl_open(filename='%s', flags=%i, ra_init=%i, para=%p): Can not load library: %s", filename, flags, ra_init, para, roar_dl_errstr(ret));
395   roar_mm_free(ret);
396   return NULL;
397  }
[5481]398#elif defined(ROAR_TARGET_WIN32)
399  ret->handle = LoadLibrary(filename);
400
401  if ( ret->handle == NULL ) {
402   roar_mm_free(ret);
403   return NULL;
404  }
[3304]405#else
[5317]406  roar_mm_free(ret);
407  roar_err_set(ROAR_ERROR_NOSYS);
408  return NULL;
[3304]409#endif
[5317]410 }
[3304]411
[5275]412 ret->para = para;
[3298]413
414 if ( ra_init ) {
[5275]415  if ( roar_dl_ra_init(ret, NULL, para) == -1 ) {
416   err = roar_error;
417   ROAR_WARN("roar_dl_open(filename='%s', flags=%i, ra_init=%i, para=%p): Can not init RA lib: %s", filename, flags, ra_init, para, roar_error2str(err));
418#if defined(ROAR_HAVE_LIBDL)
[5317]419   if ( ret->handle != NULL )
420    dlclose(ret->handle);
[5481]421#elif defined(ROAR_TARGET_WIN32)
422   if ( ret->handle != NULL )
423    FreeLibrary(ret->handle);
[5275]424#endif
425   roar_mm_free(ret);
426   roar_error = err;
427   return NULL;
428  }
[3298]429 }
430
[5275]431 if ( para != NULL )
432  roar_dl_para_ref(para);
433
[3298]434 return ret;
[3297]435}
436
[5321]437int                      roar_dl_ref    (struct roar_dl_lhandle * lhandle) {
438 if ( (void*)lhandle < (void*)128 ) {
[5438]439  ROAR_DBG("roar_dl_ref(lhandle=%p) = -1 // error=BADFH", lhandle);
[5275]440  roar_err_set(ROAR_ERROR_BADFH);
[3301]441  return -1;
[5275]442 }
[3301]443
[5321]444 lhandle->refc++;
445
[5438]446 ROAR_DBG("roar_dl_ref(lhandle=%p) = 0", lhandle);
[5321]447 return 0;
448}
449
450int                      roar_dl_unref  (struct roar_dl_lhandle * lhandle) {
451 int ret = -1;
452
453 if ( (void*)lhandle < (void*)128 ) {
[5438]454  ROAR_DBG("roar_dl_unref(lhandle=%p) = -1 // error=BADFH", lhandle);
[5321]455  roar_err_set(ROAR_ERROR_BADFH);
456  return -1;
457 }
458
[5438]459 lhandle->refc--;
[5321]460
[5438]461 if ( lhandle->refc ) {
462  ROAR_DBG("roar_dl_unref(lhandle=%p) = 0", lhandle);
[5321]463  return 0;
[5438]464 }
[5321]465
[5317]466 if ( lhandle->lib != NULL && lhandle->lib->unload != NULL ) {
467  roar_dl_context_restore(lhandle);
[3301]468  lhandle->lib->unload(lhandle->para, lhandle->lib);
[5317]469  roar_dl_context_store(lhandle);
470 }
[3301]471
[3297]472#if defined(ROAR_HAVE_LIBDL)
[5317]473 if ( lhandle->handle == NULL ) {
474  ret = 0;
475 } else {
476  ret = dlclose(_roardl2ldl(lhandle));
477 }
[5481]478#elif defined(ROAR_TARGET_WIN32)
479 if ( lhandle->handle == NULL ) {
480  ret = 0;
481 } else {
482  if ( FreeLibrary(_roardl2winhandle(lhandle)) ) {
483   ret = 0;
484  } else {
485   ret = -1;
486  }
487 }
[3297]488#else
[3304]489 ret = -1;
[3297]490#endif
[3304]491
[5312]492 if ( lhandle->context.global_data != NULL )
493  roar_mm_free(lhandle->context.global_data);
494
[5275]495 if ( lhandle->para != NULL )
496  roar_dl_para_unref(lhandle->para);
497
[5317]498 if ( lhandle->libname != NULL )
499  roar_mm_free(lhandle->libname);
500
[3304]501 roar_mm_free(lhandle);
502
[5438]503 ROAR_DBG("roar_dl_unref(lhandle=%p) = %i", lhandle, ret);
[3304]504 return ret;
[3297]505}
506
507void                   * roar_dl_getsym(struct roar_dl_lhandle * lhandle, const char * sym, int type) {
508#if defined(ROAR_HAVE_LIBDL)
[3776]509 void * ret = dlsym(_roardl2ldl(lhandle), sym);
510
[5270]511 (void)type;
512
[5317]513 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i): errno=%s, dlerror()='%s'", lhandle, sym, type, ret, strerror(errno), dlerror());
[3776]514 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = %p", lhandle, sym, type, ret);
515
516 return ret;
[5481]517#elif defined(ROAR_TARGET_WIN32)
518 FARPROC ret = GetProcAddress(_roardl2winhandle(lhandle), sym);
519 return (void*)ret;
[3297]520#else
[5317]521 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = NULL // errno=NOSYS", lhandle, sym, type, ret);
522 roar_err_set(ROAR_ERROR_NOSYS);
[3297]523 return NULL;
524#endif
525}
526
[5275]527int                      roar_dl_ra_init(struct roar_dl_lhandle * lhandle,
528                                         const char * prefix,
529                                         struct roar_dl_librarypara * para) {
[3297]530#define _SUFFIX "_roaraudio_library_init"
531 char name[80] = _SUFFIX;
532 struct roar_dl_libraryinst * (*func)(struct roar_dl_librarypara * para);
533 struct roar_dl_libraryinst * lib;
[5317]534 struct roar_dl_lhandle     * getsymhandle = lhandle;
[5312]535 void * global_data_state = NULL;
[3300]536 int i;
[3297]537
[3305]538 if ( (void*)lhandle < (void*)128 ) {
539  if ( prefix == NULL )
540   return -1;
541 } else {
[5503]542  if ( lhandle->runtime_flags & RTF_RA_INITED )
[5431]543   return 0;
544
[5317]545  if ( prefix == NULL )
546   prefix = lhandle->libname;
547
[5275]548  if ( para == NULL )
549   para = lhandle->para;
[5317]550
551  if ( lhandle->flags & ROAR_DL_FLAG_STATIC )
552   getsymhandle = ROAR_DL_HANDLE_DEFAULT;
[3305]553 }
554
[3297]555
556 if ( prefix != NULL ) {
[5008]557  roar_mm_strscpy(name, "_");
558  roar_mm_strscat(name, prefix);
559  roar_mm_strscat(name, _SUFFIX);
[3297]560 }
561
[3307]562 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): name='%s'", lhandle, prefix, name);
563
[5317]564 if ( (func = roar_dl_getsym(getsymhandle, name, -1)) == NULL ) {
565  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s') = -1", lhandle, prefix);
[3297]566  return -1;
[5317]567 }
[3297]568
[3307]569 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): func=%p", lhandle, prefix, func);
570
[3300]571 lib = func(para);
[3297]572
573 if ( lib == NULL )
574  return -1;
575
[3300]576 if ( lib->version != ROAR_DL_LIBINST_VERSION )
577  return -1;
578
579 if ( sizeof(struct roar_dl_libraryinst) > lib->len )
580  return -1;
581
[5353]582 if ( lib->host_appname != NULL || lib->host_abiversion != NULL ) {
583  // check for correct host.
584  if ( para == NULL ) {
585   roar_err_set(ROAR_ERROR_INVAL);
586   return -1;
587  }
588  if ( roar_dl_para_check_version(para, lib->host_appname, lib->host_abiversion) == -1 )
589   return -1;
590 }
591
[5347]592 if ( (lib->libdep == NULL && lib->libdep_len) || (lib->libdep != NULL && !lib->libdep_len) ) {
593  roar_err_set(ROAR_ERROR_BADLIB);
594  return -1;
595 }
596
597 if ( lib->libdep != NULL && lib->libdep_len ) {
598  // dynamic loader infos are currently not supported.
599  roar_err_set(ROAR_ERROR_NOTSUP);
600  return -1;
601 }
602
[3361]603 if ( !((void*)lhandle < (void*)128) ) {
604  lhandle->lib = lib;
[5312]605
606  if ( lib->global_data_len ) {
607   lhandle->context.global_data = roar_mm_malloc(lib->global_data_len);
608   if ( lhandle->context.global_data == NULL )
609    return -1;
610
611   if ( lib->global_data_init == NULL ) {
612    memset(lhandle->context.global_data, 0, lib->global_data_len);
613   } else {
614    memcpy(lhandle->context.global_data, lib->global_data_init, lib->global_data_len);
615   }
616  }
617 }
618
619 if ( lib->global_data_pointer != NULL ) {
620  global_data_state = *(lib->global_data_pointer);
[5313]621  if ( (void*)lhandle < (void*)128 ) {
[5312]622   *(lib->global_data_pointer) = lib->global_data_init;
623  } else {
624   *(lib->global_data_pointer) = lhandle->context.global_data;
625  }
[3361]626 }
627
[3300]628 for (i = 0; i < ROAR_DL_FN_MAX; i++) {
629  if ( lib->func[i] != NULL )
630   lib->func[i](para, lib);
631 }
632
[5312]633 if ( lib->global_data_pointer != NULL ) {
[5313]634  if ( !((void*)lhandle < (void*)128) ) {
635   *(lib->global_data_pointer) = global_data_state;
636  }
[5312]637 }
638
[5431]639 if ( !((void*)lhandle < (void*)128) )
[5503]640  lhandle->runtime_flags |= RTF_RA_INITED;
[5431]641
[3302]642 return 0;
[3297]643}
644
[5275]645const char * roar_dl_errstr(struct roar_dl_lhandle * lhandle) {
[3364]646#if defined(ROAR_HAVE_LIBDL)
[5270]647 (void)lhandle;
[3364]648 return dlerror();
[5481]649#elif defined(ROAR_TARGET_WIN32)
650 roar_err_from_errno();
651 return roar_error2str(roar_error);
[3364]652#else
653 return NULL;
654#endif
655}
656
[5275]657struct roar_dl_librarypara       * roar_dl_getpara(struct roar_dl_lhandle * lhandle) {
658 if ( (void*)lhandle < (void*)128 ) {
659  roar_err_set(ROAR_ERROR_NOTSUP);
660  return NULL;
661 }
662
663 if ( lhandle->para == NULL ) {
664  roar_err_set(ROAR_ERROR_NOENT);
665  return NULL;
666 }
667
668 if ( roar_dl_para_ref(lhandle->para) == -1 )
669  return NULL;
670
671 return lhandle->para;
672}
673
674const struct roar_dl_libraryname * roar_dl_getlibname(struct roar_dl_lhandle * lhandle) {
675 if ( (void*)lhandle < (void*)128 ) {
676  roar_err_set(ROAR_ERROR_NOTSUP);
677  return NULL;
678 }
679
680 if ( lhandle->lib == NULL ) {
681  roar_err_set(ROAR_ERROR_BADLIB);
682  return NULL;
683 }
684
685 if ( lhandle->lib->libname == NULL ) {
686  roar_err_set(ROAR_ERROR_NOENT);
687  return NULL;
688 }
689
690 if ( lhandle->lib->libname->version != ROAR_DL_LIBNAME_VERSION ) {
691  roar_err_set(ROAR_ERROR_BADVERSION);
692  return NULL;
693 }
694
695 if ( lhandle->lib->libname->len != sizeof(struct roar_dl_libraryname) ) {
696  roar_err_set(ROAR_ERROR_HOLE);
697  return NULL;
698 }
699
700 return lhandle->lib->libname;
701}
702
[5312]703int                      roar_dl_context_restore(struct roar_dl_lhandle * lhandle) {
704 struct roar_error_state error_state;
705
[5317]706 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = ?", lhandle);
707
[5312]708 if ( (void*)lhandle < (void*)128 ) {
[5317]709  ROAR_DBG("roar_dl_context_restore(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
[5312]710  roar_err_set(ROAR_ERROR_NOTSUP);
711  return -1;
712 }
713
714 roar_err_store(&error_state);
715 roar_err_restore(&(lhandle->context.error_state));
716 lhandle->context.error_state = error_state;
717
718 if ( lhandle->lib->global_data_pointer != NULL ) {
[5317]719  ROAR_DBG("roar_dl_context_restore(lhandle=%p): gptr(%p): %p -> %p", lhandle,
720           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data);
[5312]721  lhandle->context.global_data_state = *(lhandle->lib->global_data_pointer);
722  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data;
723 }
724
[5317]725 if ( lhandle->para->notifycore != NULL )
726  lhandle->context.notifycore = roar_notify_core_swap_global(lhandle->para->notifycore);
727
728 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = 0", lhandle);
[5312]729 return 0;
730}
731
732int                      roar_dl_context_store(struct roar_dl_lhandle * lhandle) {
733 struct roar_error_state error_state;
734
[5317]735 ROAR_DBG("roar_dl_context_store(lhandle=%p) = ?", lhandle);
736
[5312]737 if ( (void*)lhandle < (void*)128 ) {
[5317]738  ROAR_DBG("roar_dl_context_store(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
[5312]739  roar_err_set(ROAR_ERROR_NOTSUP);
740  return -1;
741 }
742
[5317]743 if ( lhandle->para->notifycore != NULL ) {
744  roar_notify_core_unref(roar_notify_core_swap_global(lhandle->context.notifycore));
745  roar_notify_core_unref(lhandle->context.notifycore);
746  lhandle->context.notifycore = NULL;
747 }
748
[5312]749 if ( lhandle->lib->global_data_pointer != NULL ) {
[5317]750  ROAR_DBG("roar_dl_context_store(lhandle=%p): gptr(%p): %p -> %p", lhandle,
751           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data_state);
[5312]752  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data_state;
753 }
754
755 roar_err_store(&error_state);
756 roar_err_restore(&(lhandle->context.error_state));
757 lhandle->context.error_state = error_state;
758
[5317]759 ROAR_DBG("roar_dl_context_store(lhandle=%p) = 0", lhandle);
[5312]760 return 0;
761}
762
[5317]763int                      roar_dl_appsched_trigger(struct roar_dl_lhandle * lhandle, enum roar_dl_appsched_trigger trigger) {
[5335]764 int (*func)  (struct roar_dl_librarypara * para) = NULL;
[5317]765 int ret;
766
767 if ( (void*)lhandle < (void*)128 ) {
768  roar_err_set(ROAR_ERROR_NOTSUP);
769  return -1;
770 }
771
[5446]772 if ( lhandle->lib == NULL ) {
773  roar_err_set(ROAR_ERROR_TYPEMM);
774  return -1;
775 }
776
[5317]777 if ( lhandle->lib->appsched == NULL ) {
778  roar_err_set(ROAR_ERROR_NOENT);
779  return -1;
780 }
781
782 switch (trigger) {
783#define _trig(lname,uname) \
784  case ROAR_DL_APPSCHED_ ## uname :             \
[5335]785    func = lhandle->lib->appsched->lname;       \
[5317]786   break;
787  _trig(init, INIT);
788  _trig(free, FREE);
789  _trig(update, UPDATE);
[5335]790  _trig(tick, TICK);
791  _trig(wait, WAIT);
792// use ifndef here so warnings of unhandled enum values will be shown in DEBUG mode.
793#ifndef DEBUG
794  default:
795    roar_err_set(ROAR_ERROR_BADRQC);
796    return -1;
797   break;
798#endif
[5317]799 }
800
[5335]801 if ( func == NULL ) {
[5503]802  if ( trigger == ROAR_DL_APPSCHED_INIT ) {
803   lhandle->runtime_flags |= RTF_APPSCHED_INITED|RTF_APPSCHED_FREED;
804   lhandle->runtime_flags -= RTF_APPSCHED_FREED;
805  } else if ( trigger == ROAR_DL_APPSCHED_FREE ) {
806   lhandle->runtime_flags |= RTF_APPSCHED_INITED|RTF_APPSCHED_FREED;
807   lhandle->runtime_flags -= RTF_APPSCHED_INITED;
808  }
[5335]809  roar_err_set(ROAR_ERROR_NOENT);
810  return -1;
811 }
812
[5503]813 if ( trigger == ROAR_DL_APPSCHED_INIT ) {
814  if ( lhandle->runtime_flags & RTF_APPSCHED_INITED ) {
815   roar_err_set(ROAR_ERROR_BUSY);
816   return -1;
817  }
818 } else {
819  if ( !(lhandle->runtime_flags & RTF_APPSCHED_INITED) ) {
820   roar_err_set(ROAR_ERROR_BUSY);
821   return -1;
822  }
823 }
824
[5335]825 roar_dl_context_restore(lhandle);
826 ret = func(lhandle->para);
827 roar_dl_context_store(lhandle);
[5503]828
829 if ( trigger == ROAR_DL_APPSCHED_INIT ) {
830  lhandle->runtime_flags |= RTF_APPSCHED_INITED|RTF_APPSCHED_FREED;
831  lhandle->runtime_flags -= RTF_APPSCHED_FREED;
832 } else if ( trigger == ROAR_DL_APPSCHED_FREE ) {
833  lhandle->runtime_flags |= RTF_APPSCHED_INITED|RTF_APPSCHED_FREED;
834  lhandle->runtime_flags -= RTF_APPSCHED_INITED;
835 }
836
[5335]837 return ret;
[5317]838}
839
[3297]840//ll
Note: See TracBrowser for help on using the repository browser.