source: roaraudio/libroar/roardl.c @ 5431:4cd68e4f7a78

Last change on this file since 5431:4cd68e4f7a78 was 5431:4cd68e4f7a78, checked in by phi, 10 years ago

protect against double ra_init

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