source: roaraudio/libroar/roardl.c @ 5438:4eb05969f66c

Last change on this file since 5438:4eb05969f66c was 5438:4eb05969f66c, checked in by phi, 12 years ago

fix code so refcount is correct and avoid double free

File size: 20.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
[5275]46struct roar_dl_lhandle {
[5317]47 size_t refc; // currently unused.
48 int flags;
49 char * libname; // only used for ROAR_DL_FLAG_STATIC.
[5275]50 struct roar_dl_librarypara * para;
51 struct roar_dl_libraryinst * lib;
[5312]52 struct {
53  struct roar_error_state error_state;
54  void *  global_data;
55  void *  global_data_state;
[5317]56  struct roar_notify_core * notifycore;
[5312]57 } context;
[5431]58 int ra_inited;
[5275]59#if defined(ROAR_HAVE_LIBDL)
60 void * handle;
61#endif
62};
63
64
65struct roar_dl_librarypara * roar_dl_para_new(const char * args, void * binargv,
66                                              const char * appname, const char * abiversion) {
67 struct roar_dl_librarypara * ret = roar_mm_malloc(sizeof(struct roar_dl_librarypara));
68 ssize_t argc;
69 int err;
70
71 if ( ret == NULL )
72  return NULL;
73
74 memset(ret, 0, sizeof(struct roar_dl_librarypara));
75
76 ret->version    = ROAR_DL_LIBPARA_VERSION;
77 ret->len        = sizeof(struct roar_dl_librarypara);
78 ret->refc       = 1;
79 ret->argc       = 0;
80 ret->argv       = NULL;
81 ret->args_store = NULL;
82 ret->binargv    = binargv;
83 ret->appname    = appname;
84 ret->abiversion = abiversion;
85
86 if ( args != NULL ) {
87  ret->args_store = roar_mm_strdup(args);
88  if ( ret->args_store == NULL ) {
89   err = roar_error;
90   roar_mm_free(ret);
91   roar_error = err;
92   return NULL;
93  }
94
95  argc = roar_keyval_split(&(ret->argv), ret->args_store, NULL, NULL, 0);
96  if ( argc == -1 ) {
97   err = roar_error;
98   roar_mm_free(ret->args_store);
99   roar_mm_free(ret);
100   roar_error = err;
101   return NULL;
102  }
103
104  ret->argc = argc;
105 }
106
107 return ret;
108}
109
110int roar_dl_para_ref                    (struct roar_dl_librarypara * para) {
111 if ( para == NULL ) {
[5438]112  ROAR_DBG("roar_dl_para_ref(para=%p) = -1 // error=FAULT", para);
[5275]113  roar_err_set(ROAR_ERROR_FAULT);
114  return -1;
115 }
116
117 para->refc++;
118
[5438]119 ROAR_DBG("roar_dl_para_ref(para=%p) = 0", para);
[5275]120 return 0;
121}
122
123int roar_dl_para_unref                  (struct roar_dl_librarypara * para) {
124 if ( para == NULL ) {
[5438]125  ROAR_DBG("roar_dl_para_unref(para=%p) = -1 // error=FAULT", para);
[5275]126  roar_err_set(ROAR_ERROR_FAULT);
127  return -1;
128 }
129
130 para->refc--;
131
[5438]132 if ( para->refc ) {
133  ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
[5317]134  return 0;
[5438]135 }
[5317]136
137 if ( para->notifycore != NULL )
138  roar_notify_core_unref(para->notifycore);
139
140 if ( para->args_store != NULL ) {
141  roar_mm_free(para->args_store);
142  roar_mm_free(para->argv);
[5275]143 }
144
[5317]145 roar_mm_free(para);
146
[5438]147 ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
[5275]148 return 0;
149}
150int roar_dl_para_check_version          (struct roar_dl_librarypara * para,
151                                         const char * appname, const char * abiversion) {
152 if ( para == NULL ) {
153  roar_err_set(ROAR_ERROR_FAULT);
154  return -1;
155 }
156
157 // check if both appnames are NULL or non-NULL.
158 if ( (para->appname == NULL && appname != NULL) || (para->appname != NULL && appname == NULL) ) {
[5371]159  roar_err_set(ROAR_ERROR_BADHOST);
[5275]160  return -1;
161 }
162
163 // check if the appname matches if given.
164 if ( para->appname != NULL && !!strcmp(para->appname, appname) ) {
[5371]165  roar_err_set(ROAR_ERROR_BADHOST);
[5275]166  return -1;
167 }
168
169 // check if both ABI versions are NULL or non-NULL.
170 if ( (para->abiversion == NULL && abiversion != NULL) || (para->abiversion != NULL && abiversion == NULL) ) {
171  roar_err_set(ROAR_ERROR_BADVERSION);
172  return -1;
173 }
174
175 // check if the ABI versions matches if given.
176 if ( para->abiversion != NULL && !!strcmp(para->abiversion, abiversion) ) {
177  roar_err_set(ROAR_ERROR_BADVERSION);
178  return -1;
179 }
180
181 return 0;
182}
183
184
[3297]185#if defined(ROAR_HAVE_LIBDL)
186static void * _roardl2ldl (struct roar_dl_lhandle * lhandle) {
[5317]187 ROAR_DBG("_roardl2ldl(lhandle=%p) = ?", lhandle);
188
189 if ( lhandle == ROAR_DL_HANDLE_DEFAULT ) {
190  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_DEFAULT);
[3297]191  return RTLD_DEFAULT;
[5317]192 }
[3297]193
[5317]194 if ( lhandle == ROAR_DL_HANDLE_NEXT ) {
195  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_NEXT);
[3297]196  return RTLD_NEXT;
[5317]197 }
[3297]198
[5317]199 ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)(lhandle->handle));
[3297]200 return lhandle->handle;
201}
202#endif
203
[5427]204#ifdef ROAR_HAVE_H_DIRENT
205// pvn = prefix, host vendor, host name
206static struct roar_dl_lhandle * _load_from_path_pvn(const char * name,
207                                                    int flags, int ra_init,
208                                                    struct roar_dl_librarypara * para,
209                                                    const char * prefix,
210                                                    const char * hostvendor,
211                                                    const char * hostname) {
212 struct roar_dl_lhandle * ret = NULL;
213 int i, j;
214 char path[1024];
215 const char * path_format[] = {"%s/%s/%s", "%s/%s/universal", "%s/universal/universal"};
216 DIR * dir;
217 struct dirent * dirent;
218 char file[1024];
219 const char * file_format[] = {"%s/%s/%s", "%s/%s/%s" ROAR_SHARED_SUFFIX, "%s/%s/lib%s" ROAR_SHARED_SUFFIX};
220//  cont->handle[idx] = roar_dl_open(name, ROAR_DL_FLAG_DEFAULTS, 1, para);
221//#vars: $PREFIX_PLUGINS, $hostvendor, $hostname, $name
222//#search order: $PREFIX_PLUGINS/{$hostvendor/{$hostname,universal},universal/universal}/*/{,lib}$name.so
223
224 for (i = 0; i < 3; i++) {
225  snprintf(path, sizeof(path), path_format[i], prefix, hostvendor, hostname);
226  dir = opendir(path);
227  if ( dir == NULL )
228   continue;
229
230  while ((dirent = readdir(dir)) != NULL) {
231   if ( !strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..") )
232    continue;
233
234   for (j = 0; j < 3; j++) {
235    snprintf(file, sizeof(file), file_format[j], path, dirent->d_name, name);
236    ret = roar_dl_open(file, flags, ra_init, para);
237    if ( ret != NULL ) {
238     closedir(dir);
239     return ret;
240    }
241   }
242  }
243
244  closedir(dir);
245 }
246
247 return NULL;
248}
249
250static struct roar_dl_lhandle * _load_from_path(const char * name, int flags, int ra_init,
251                                                struct roar_dl_librarypara * para) {
252 struct roar_dl_lhandle * ret = NULL;
253 char * host = NULL;
254 char * hostvendor_buffer = NULL;
255 char * hostvendor = NULL;
256 char * hostname = NULL;
257 char * c, * d;
258
259 if ( para != NULL && para->appname != NULL && para->appname[0] != 0 ) {
260  host = roar_mm_strdup(para->appname);
261
262  // if we are out of memory we will likely not pass the rest, so just return in error.
263  if ( host == NULL )
264   return NULL;
265
266  hostname = host;
267  c = strstr(host, "<");
268  if ( c != NULL ) {
269   while (c[-1] == ' ') c--;
270   *c = 0;
271   c++;
272   while (*c == ' ' || *c == '<') c++;
273   if ( *c ) {
274    d = strstr(c, ">");
275    if ( d != NULL )
276     *d = 0;
277
278    d = strstr(c, "/");
279    if ( d != NULL ) {
280     *d = '-';
281     hostvendor = c;
282    } else {
283     hostvendor_buffer = roar_mm_malloc(roar_mm_strlen(c) + 1 /* tailing \0 */ + 6 /* "unreg-" */);
284
285     // see above
286     if ( hostvendor_buffer == NULL ) {
287      roar_mm_free(host);
288      return NULL;
289     }
290
291     strcpy(hostvendor_buffer, "unreg-");
292     strcat(hostvendor_buffer, c);
293     hostvendor = hostvendor_buffer;
294    }
295   }
296  }
297 }
298
299 if ( hostvendor == NULL )
300  hostvendor = "universal";
301
302 if ( hostname == NULL )
303  hostname = "universal";
304
305 ret = _load_from_path_pvn(name, flags, ra_init, para, ROAR_PREFIX_PLUGINS, hostvendor, hostname);
306
307 if ( host != NULL )
308  roar_mm_free(host);
309 if ( hostvendor_buffer != NULL )
310  roar_mm_free(hostvendor_buffer);
311 return ret;
312}
313#endif
314
315static struct roar_dl_lhandle * _roar_dl_open_pluginpath(const char * filename, int flags,
316                                      int ra_init, struct roar_dl_librarypara * para) {
317 flags |= ROAR_DL_FLAG_PLUGINPATH;
318 flags -= ROAR_DL_FLAG_PLUGINPATH;
319
320#ifdef ROAR_HAVE_H_DIRENT
[5430]321 // do normal open for everything with a path name.
322 if ( strstr(filename, "/") != NULL )
323  return roar_dl_open(filename, flags, ra_init, para);
324
[5427]325 return _load_from_path(filename, flags, ra_init, para);
326#else
327 // fall back to system open function.
328 return roar_dl_open(filename, flags, ra_init, para);
329#endif
330}
331
[5275]332struct roar_dl_lhandle * roar_dl_open(const char * filename, int flags,
333                                      int ra_init, struct roar_dl_librarypara * para) {
[3298]334 struct roar_dl_lhandle * ret = NULL;
[5317]335#if defined(ROAR_HAVE_LIBDL)
336#ifdef RTLD_DEEPBIND
[5344]337 int libdl_flags = RTLD_DEEPBIND;
[5317]338#else
[5344]339 int libdl_flags = 0;
[5317]340#endif
341#endif
[5275]342 int err;
[3298]343
[5427]344 switch (flags) {
345  case ROAR_DL_FLAG_DEFAULTS: flags = ROAR_DL_FLAG_NONE;       break;
346  case ROAR_DL_FLAG_PLUGIN:   flags = ROAR_DL_FLAG_PLUGINPATH; break;
347 }
348
349 if ( flags & ROAR_DL_FLAG_PLUGINPATH )
350  return _roar_dl_open_pluginpath(filename, flags, ra_init, para);
[3304]351
[5344]352#if defined(ROAR_HAVE_LIBDL)
353 if ( flags & ROAR_DL_FLAG_LAZY ) {
354  libdl_flags |= RTLD_LAZY;
355 } else {
356  libdl_flags |= RTLD_NOW;
357 }
358#endif
359
[3304]360 if ( (ret = roar_mm_malloc(sizeof(struct roar_dl_lhandle))) == NULL )
361  return NULL;
362
363 memset(ret, 0, sizeof(struct roar_dl_lhandle));
364
[5312]365 roar_err_initstore(&(ret->context.error_state));
366
[5317]367 ret->flags = flags;
[5321]368 ret->refc  = 1;
[3366]369
[5317]370 if ( flags & ROAR_DL_FLAG_STATIC ) {
371  if ( filename == NULL ) {
372   ret->libname = NULL;
373  } else {
374   ret->libname = roar_mm_strdup(filename);
375  }
376 } else {
377#if defined(ROAR_HAVE_LIBDL)
378  ret->handle = dlopen(filename, libdl_flags);
[3304]379
[5317]380  if ( ret->handle == NULL ) {
381   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));
382   roar_mm_free(ret);
383   return NULL;
384  }
[3304]385#else
[5317]386  roar_mm_free(ret);
387  roar_err_set(ROAR_ERROR_NOSYS);
388  return NULL;
[3304]389#endif
[5317]390 }
[3304]391
[5275]392 ret->para = para;
[3298]393
394 if ( ra_init ) {
[5275]395  if ( roar_dl_ra_init(ret, NULL, para) == -1 ) {
396   err = roar_error;
397   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));
398#if defined(ROAR_HAVE_LIBDL)
[5317]399   if ( ret->handle != NULL )
400    dlclose(ret->handle);
[5275]401#endif
402   roar_mm_free(ret);
403   roar_error = err;
404   return NULL;
405  }
[3298]406 }
407
[5275]408 if ( para != NULL )
409  roar_dl_para_ref(para);
410
[3298]411 return ret;
[3297]412}
413
[5321]414int                      roar_dl_ref    (struct roar_dl_lhandle * lhandle) {
415 if ( (void*)lhandle < (void*)128 ) {
[5438]416  ROAR_DBG("roar_dl_ref(lhandle=%p) = -1 // error=BADFH", lhandle);
[5275]417  roar_err_set(ROAR_ERROR_BADFH);
[3301]418  return -1;
[5275]419 }
[3301]420
[5321]421 lhandle->refc++;
422
[5438]423 ROAR_DBG("roar_dl_ref(lhandle=%p) = 0", lhandle);
[5321]424 return 0;
425}
426
427int                      roar_dl_unref  (struct roar_dl_lhandle * lhandle) {
428 int ret = -1;
429
430 if ( (void*)lhandle < (void*)128 ) {
[5438]431  ROAR_DBG("roar_dl_unref(lhandle=%p) = -1 // error=BADFH", lhandle);
[5321]432  roar_err_set(ROAR_ERROR_BADFH);
433  return -1;
434 }
435
[5438]436 lhandle->refc--;
[5321]437
[5438]438 if ( lhandle->refc ) {
439  ROAR_DBG("roar_dl_unref(lhandle=%p) = 0", lhandle);
[5321]440  return 0;
[5438]441 }
[5321]442
[5317]443 if ( lhandle->lib != NULL && lhandle->lib->unload != NULL ) {
444  roar_dl_context_restore(lhandle);
[3301]445  lhandle->lib->unload(lhandle->para, lhandle->lib);
[5317]446  roar_dl_context_store(lhandle);
447 }
[3301]448
[3297]449#if defined(ROAR_HAVE_LIBDL)
[5317]450 if ( lhandle->handle == NULL ) {
451  ret = 0;
452 } else {
453  ret = dlclose(_roardl2ldl(lhandle));
454 }
[3297]455#else
[3304]456 ret = -1;
[3297]457#endif
[3304]458
[5312]459 if ( lhandle->context.global_data != NULL )
460  roar_mm_free(lhandle->context.global_data);
461
[5275]462 if ( lhandle->para != NULL )
463  roar_dl_para_unref(lhandle->para);
464
[5317]465 if ( lhandle->libname != NULL )
466  roar_mm_free(lhandle->libname);
467
[3304]468 roar_mm_free(lhandle);
469
[5438]470 ROAR_DBG("roar_dl_unref(lhandle=%p) = %i", lhandle, ret);
[3304]471 return ret;
[3297]472}
473
474void                   * roar_dl_getsym(struct roar_dl_lhandle * lhandle, const char * sym, int type) {
475#if defined(ROAR_HAVE_LIBDL)
[3776]476 void * ret = dlsym(_roardl2ldl(lhandle), sym);
477
[5270]478 (void)type;
479
[5317]480 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i): errno=%s, dlerror()='%s'", lhandle, sym, type, ret, strerror(errno), dlerror());
[3776]481 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = %p", lhandle, sym, type, ret);
482
483 return ret;
[3297]484#else
[5317]485 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = NULL // errno=NOSYS", lhandle, sym, type, ret);
486 roar_err_set(ROAR_ERROR_NOSYS);
[3297]487 return NULL;
488#endif
489}
490
[5275]491int                      roar_dl_ra_init(struct roar_dl_lhandle * lhandle,
492                                         const char * prefix,
493                                         struct roar_dl_librarypara * para) {
[3297]494#define _SUFFIX "_roaraudio_library_init"
495 char name[80] = _SUFFIX;
496 struct roar_dl_libraryinst * (*func)(struct roar_dl_librarypara * para);
497 struct roar_dl_libraryinst * lib;
[5317]498 struct roar_dl_lhandle     * getsymhandle = lhandle;
[5312]499 void * global_data_state = NULL;
[3300]500 int i;
[3297]501
[3305]502 if ( (void*)lhandle < (void*)128 ) {
503  if ( prefix == NULL )
504   return -1;
505 } else {
[5431]506  if ( lhandle->ra_inited )
507   return 0;
508
[5317]509  if ( prefix == NULL )
510   prefix = lhandle->libname;
511
[5275]512  if ( para == NULL )
513   para = lhandle->para;
[5317]514
515  if ( lhandle->flags & ROAR_DL_FLAG_STATIC )
516   getsymhandle = ROAR_DL_HANDLE_DEFAULT;
[3305]517 }
518
[3297]519
520 if ( prefix != NULL ) {
[5008]521  roar_mm_strscpy(name, "_");
522  roar_mm_strscat(name, prefix);
523  roar_mm_strscat(name, _SUFFIX);
[3297]524 }
525
[3307]526 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): name='%s'", lhandle, prefix, name);
527
[5317]528 if ( (func = roar_dl_getsym(getsymhandle, name, -1)) == NULL ) {
529  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s') = -1", lhandle, prefix);
[3297]530  return -1;
[5317]531 }
[3297]532
[3307]533 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): func=%p", lhandle, prefix, func);
534
[3300]535 lib = func(para);
[3297]536
537 if ( lib == NULL )
538  return -1;
539
[3300]540 if ( lib->version != ROAR_DL_LIBINST_VERSION )
541  return -1;
542
543 if ( sizeof(struct roar_dl_libraryinst) > lib->len )
544  return -1;
545
[5353]546 if ( lib->host_appname != NULL || lib->host_abiversion != NULL ) {
547  // check for correct host.
548  if ( para == NULL ) {
549   roar_err_set(ROAR_ERROR_INVAL);
550   return -1;
551  }
552  if ( roar_dl_para_check_version(para, lib->host_appname, lib->host_abiversion) == -1 )
553   return -1;
554 }
555
[5347]556 if ( (lib->libdep == NULL && lib->libdep_len) || (lib->libdep != NULL && !lib->libdep_len) ) {
557  roar_err_set(ROAR_ERROR_BADLIB);
558  return -1;
559 }
560
561 if ( lib->libdep != NULL && lib->libdep_len ) {
562  // dynamic loader infos are currently not supported.
563  roar_err_set(ROAR_ERROR_NOTSUP);
564  return -1;
565 }
566
[3361]567 if ( !((void*)lhandle < (void*)128) ) {
568  lhandle->lib = lib;
[5312]569
570  if ( lib->global_data_len ) {
571   lhandle->context.global_data = roar_mm_malloc(lib->global_data_len);
572   if ( lhandle->context.global_data == NULL )
573    return -1;
574
575   if ( lib->global_data_init == NULL ) {
576    memset(lhandle->context.global_data, 0, lib->global_data_len);
577   } else {
578    memcpy(lhandle->context.global_data, lib->global_data_init, lib->global_data_len);
579   }
580  }
581 }
582
583 if ( lib->global_data_pointer != NULL ) {
584  global_data_state = *(lib->global_data_pointer);
[5313]585  if ( (void*)lhandle < (void*)128 ) {
[5312]586   *(lib->global_data_pointer) = lib->global_data_init;
587  } else {
588   *(lib->global_data_pointer) = lhandle->context.global_data;
589  }
[3361]590 }
591
[3300]592 for (i = 0; i < ROAR_DL_FN_MAX; i++) {
593  if ( lib->func[i] != NULL )
594   lib->func[i](para, lib);
595 }
596
[5312]597 if ( lib->global_data_pointer != NULL ) {
[5313]598  if ( !((void*)lhandle < (void*)128) ) {
599   *(lib->global_data_pointer) = global_data_state;
600  }
[5312]601 }
602
[5431]603 if ( !((void*)lhandle < (void*)128) )
604  lhandle->ra_inited = 1;
605
[3302]606 return 0;
[3297]607}
608
[5275]609const char * roar_dl_errstr(struct roar_dl_lhandle * lhandle) {
[3364]610#if defined(ROAR_HAVE_LIBDL)
[5270]611 (void)lhandle;
[3364]612 return dlerror();
613#else
614 return NULL;
615#endif
616}
617
[5275]618struct roar_dl_librarypara       * roar_dl_getpara(struct roar_dl_lhandle * lhandle) {
619 if ( (void*)lhandle < (void*)128 ) {
620  roar_err_set(ROAR_ERROR_NOTSUP);
621  return NULL;
622 }
623
624 if ( lhandle->para == NULL ) {
625  roar_err_set(ROAR_ERROR_NOENT);
626  return NULL;
627 }
628
629 if ( roar_dl_para_ref(lhandle->para) == -1 )
630  return NULL;
631
632 return lhandle->para;
633}
634
635const struct roar_dl_libraryname * roar_dl_getlibname(struct roar_dl_lhandle * lhandle) {
636 if ( (void*)lhandle < (void*)128 ) {
637  roar_err_set(ROAR_ERROR_NOTSUP);
638  return NULL;
639 }
640
641 if ( lhandle->lib == NULL ) {
642  roar_err_set(ROAR_ERROR_BADLIB);
643  return NULL;
644 }
645
646 if ( lhandle->lib->libname == NULL ) {
647  roar_err_set(ROAR_ERROR_NOENT);
648  return NULL;
649 }
650
651 if ( lhandle->lib->libname->version != ROAR_DL_LIBNAME_VERSION ) {
652  roar_err_set(ROAR_ERROR_BADVERSION);
653  return NULL;
654 }
655
656 if ( lhandle->lib->libname->len != sizeof(struct roar_dl_libraryname) ) {
657  roar_err_set(ROAR_ERROR_HOLE);
658  return NULL;
659 }
660
661 return lhandle->lib->libname;
662}
663
[5312]664int                      roar_dl_context_restore(struct roar_dl_lhandle * lhandle) {
665 struct roar_error_state error_state;
666
[5317]667 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = ?", lhandle);
668
[5312]669 if ( (void*)lhandle < (void*)128 ) {
[5317]670  ROAR_DBG("roar_dl_context_restore(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
[5312]671  roar_err_set(ROAR_ERROR_NOTSUP);
672  return -1;
673 }
674
675 roar_err_store(&error_state);
676 roar_err_restore(&(lhandle->context.error_state));
677 lhandle->context.error_state = error_state;
678
679 if ( lhandle->lib->global_data_pointer != NULL ) {
[5317]680  ROAR_DBG("roar_dl_context_restore(lhandle=%p): gptr(%p): %p -> %p", lhandle,
681           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data);
[5312]682  lhandle->context.global_data_state = *(lhandle->lib->global_data_pointer);
683  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data;
684 }
685
[5317]686 if ( lhandle->para->notifycore != NULL )
687  lhandle->context.notifycore = roar_notify_core_swap_global(lhandle->para->notifycore);
688
689 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = 0", lhandle);
[5312]690 return 0;
691}
692
693int                      roar_dl_context_store(struct roar_dl_lhandle * lhandle) {
694 struct roar_error_state error_state;
695
[5317]696 ROAR_DBG("roar_dl_context_store(lhandle=%p) = ?", lhandle);
697
[5312]698 if ( (void*)lhandle < (void*)128 ) {
[5317]699  ROAR_DBG("roar_dl_context_store(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
[5312]700  roar_err_set(ROAR_ERROR_NOTSUP);
701  return -1;
702 }
703
[5317]704 if ( lhandle->para->notifycore != NULL ) {
705  roar_notify_core_unref(roar_notify_core_swap_global(lhandle->context.notifycore));
706  roar_notify_core_unref(lhandle->context.notifycore);
707  lhandle->context.notifycore = NULL;
708 }
709
[5312]710 if ( lhandle->lib->global_data_pointer != NULL ) {
[5317]711  ROAR_DBG("roar_dl_context_store(lhandle=%p): gptr(%p): %p -> %p", lhandle,
712           lhandle->lib->global_data_pointer, *(lhandle->lib->global_data_pointer), lhandle->context.global_data_state);
[5312]713  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data_state;
714 }
715
716 roar_err_store(&error_state);
717 roar_err_restore(&(lhandle->context.error_state));
718 lhandle->context.error_state = error_state;
719
[5317]720 ROAR_DBG("roar_dl_context_store(lhandle=%p) = 0", lhandle);
[5312]721 return 0;
722}
723
[5317]724int                      roar_dl_appsched_trigger(struct roar_dl_lhandle * lhandle, enum roar_dl_appsched_trigger trigger) {
[5335]725 int (*func)  (struct roar_dl_librarypara * para) = NULL;
[5317]726 int ret;
727
728 if ( (void*)lhandle < (void*)128 ) {
729  roar_err_set(ROAR_ERROR_NOTSUP);
730  return -1;
731 }
732
733 if ( lhandle->lib->appsched == NULL ) {
734  roar_err_set(ROAR_ERROR_NOENT);
735  return -1;
736 }
737
738 switch (trigger) {
739#define _trig(lname,uname) \
740  case ROAR_DL_APPSCHED_ ## uname :             \
[5335]741    func = lhandle->lib->appsched->lname;       \
[5317]742   break;
743  _trig(init, INIT);
744  _trig(free, FREE);
745  _trig(update, UPDATE);
[5335]746  _trig(tick, TICK);
747  _trig(wait, WAIT);
748// use ifndef here so warnings of unhandled enum values will be shown in DEBUG mode.
749#ifndef DEBUG
750  default:
751    roar_err_set(ROAR_ERROR_BADRQC);
752    return -1;
753   break;
754#endif
[5317]755 }
756
[5335]757 if ( func == NULL ) {
758  roar_err_set(ROAR_ERROR_NOENT);
759  return -1;
760 }
761
762 roar_dl_context_restore(lhandle);
763 ret = func(lhandle->para);
764 roar_dl_context_store(lhandle);
765 return ret;
[5317]766}
767
[3297]768//ll
Note: See TracBrowser for help on using the repository browser.