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
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
46#define RTF_RA_INITED       0x0001
47#define RTF_APPSCHED_INITED 0x0002
48#define RTF_APPSCHED_FREED  0x0004
49
50struct roar_dl_lhandle {
51 size_t refc; // currently unused.
52 int flags;
53 char * libname; // only used for ROAR_DL_FLAG_STATIC.
54 struct roar_dl_librarypara * para;
55 struct roar_dl_libraryinst * lib;
56 struct {
57  struct roar_error_state error_state;
58  void *  global_data;
59  void *  global_data_state;
60  struct roar_notify_core * notifycore;
61 } context;
62 unsigned int runtime_flags;
63#if defined(ROAR_HAVE_LIBDL)
64 void * handle;
65#elif defined(ROAR_TARGET_WIN32)
66 HMODULE handle;
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
101  argc = roar_keyval_split(&(ret->argv), ret->args_store, NULL, NULL, 1);
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 ) {
118  ROAR_DBG("roar_dl_para_ref(para=%p) = -1 // error=FAULT", para);
119  roar_err_set(ROAR_ERROR_FAULT);
120  return -1;
121 }
122
123 para->refc++;
124
125 ROAR_DBG("roar_dl_para_ref(para=%p) = 0", para);
126 return 0;
127}
128
129int roar_dl_para_unref                  (struct roar_dl_librarypara * para) {
130 if ( para == NULL ) {
131  ROAR_DBG("roar_dl_para_unref(para=%p) = -1 // error=FAULT", para);
132  roar_err_set(ROAR_ERROR_FAULT);
133  return -1;
134 }
135
136 para->refc--;
137
138 if ( para->refc ) {
139  ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
140  return 0;
141 }
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);
149 }
150
151 roar_mm_free(para);
152
153 ROAR_DBG("roar_dl_para_unref(para=%p) = 0", para);
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) ) {
165  roar_err_set(ROAR_ERROR_BADHOST);
166  return -1;
167 }
168
169 // check if the appname matches if given.
170 if ( para->appname != NULL && !!strcmp(para->appname, appname) ) {
171  roar_err_set(ROAR_ERROR_BADHOST);
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
191#if defined(ROAR_HAVE_LIBDL)
192static void * _roardl2ldl (struct roar_dl_lhandle * lhandle) {
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);
197  return RTLD_DEFAULT;
198 }
199
200 if ( lhandle == ROAR_DL_HANDLE_NEXT ) {
201  ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)RTLD_NEXT);
202  return RTLD_NEXT;
203 }
204
205 ROAR_DBG("_roardl2ldl(lhandle=%p) = %p", lhandle, (void*)(lhandle->handle));
206 return lhandle->handle;
207}
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}
215#endif
216
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
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
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
345struct roar_dl_lhandle * roar_dl_open(const char * filename, int flags,
346                                      int ra_init, struct roar_dl_librarypara * para) {
347 struct roar_dl_lhandle * ret = NULL;
348#if defined(ROAR_HAVE_LIBDL)
349#ifdef RTLD_DEEPBIND
350 int libdl_flags = RTLD_DEEPBIND;
351#else
352 int libdl_flags = 0;
353#endif
354#endif
355 int err;
356
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);
364
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
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
378 roar_err_initstore(&(ret->context.error_state));
379
380 ret->flags = flags;
381 ret->refc  = 1;
382
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);
392
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  }
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  }
405#else
406  roar_mm_free(ret);
407  roar_err_set(ROAR_ERROR_NOSYS);
408  return NULL;
409#endif
410 }
411
412 ret->para = para;
413
414 if ( ra_init ) {
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)
419   if ( ret->handle != NULL )
420    dlclose(ret->handle);
421#elif defined(ROAR_TARGET_WIN32)
422   if ( ret->handle != NULL )
423    FreeLibrary(ret->handle);
424#endif
425   roar_mm_free(ret);
426   roar_error = err;
427   return NULL;
428  }
429 }
430
431 if ( para != NULL )
432  roar_dl_para_ref(para);
433
434 return ret;
435}
436
437int                      roar_dl_ref    (struct roar_dl_lhandle * lhandle) {
438 if ( (void*)lhandle < (void*)128 ) {
439  ROAR_DBG("roar_dl_ref(lhandle=%p) = -1 // error=BADFH", lhandle);
440  roar_err_set(ROAR_ERROR_BADFH);
441  return -1;
442 }
443
444 lhandle->refc++;
445
446 ROAR_DBG("roar_dl_ref(lhandle=%p) = 0", lhandle);
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 ) {
454  ROAR_DBG("roar_dl_unref(lhandle=%p) = -1 // error=BADFH", lhandle);
455  roar_err_set(ROAR_ERROR_BADFH);
456  return -1;
457 }
458
459 lhandle->refc--;
460
461 if ( lhandle->refc ) {
462  ROAR_DBG("roar_dl_unref(lhandle=%p) = 0", lhandle);
463  return 0;
464 }
465
466 if ( lhandle->lib != NULL && lhandle->lib->unload != NULL ) {
467  roar_dl_context_restore(lhandle);
468  lhandle->lib->unload(lhandle->para, lhandle->lib);
469  roar_dl_context_store(lhandle);
470 }
471
472#if defined(ROAR_HAVE_LIBDL)
473 if ( lhandle->handle == NULL ) {
474  ret = 0;
475 } else {
476  ret = dlclose(_roardl2ldl(lhandle));
477 }
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 }
488#else
489 ret = -1;
490#endif
491
492 if ( lhandle->context.global_data != NULL )
493  roar_mm_free(lhandle->context.global_data);
494
495 if ( lhandle->para != NULL )
496  roar_dl_para_unref(lhandle->para);
497
498 if ( lhandle->libname != NULL )
499  roar_mm_free(lhandle->libname);
500
501 roar_mm_free(lhandle);
502
503 ROAR_DBG("roar_dl_unref(lhandle=%p) = %i", lhandle, ret);
504 return ret;
505}
506
507void                   * roar_dl_getsym(struct roar_dl_lhandle * lhandle, const char * sym, int type) {
508#if defined(ROAR_HAVE_LIBDL)
509 void * ret = dlsym(_roardl2ldl(lhandle), sym);
510
511 (void)type;
512
513 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i): errno=%s, dlerror()='%s'", lhandle, sym, type, ret, strerror(errno), dlerror());
514 ROAR_DBG("roar_dl_getsym(lhandle=%p, sym='%s', type=%i) = %p", lhandle, sym, type, ret);
515
516 return ret;
517#elif defined(ROAR_TARGET_WIN32)
518 FARPROC ret = GetProcAddress(_roardl2winhandle(lhandle), sym);
519 return (void*)ret;
520#else
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);
523 return NULL;
524#endif
525}
526
527int                      roar_dl_ra_init(struct roar_dl_lhandle * lhandle,
528                                         const char * prefix,
529                                         struct roar_dl_librarypara * para) {
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;
534 struct roar_dl_lhandle     * getsymhandle = lhandle;
535 void * global_data_state = NULL;
536 int i;
537
538 if ( (void*)lhandle < (void*)128 ) {
539  if ( prefix == NULL )
540   return -1;
541 } else {
542  if ( lhandle->runtime_flags & RTF_RA_INITED )
543   return 0;
544
545  if ( prefix == NULL )
546   prefix = lhandle->libname;
547
548  if ( para == NULL )
549   para = lhandle->para;
550
551  if ( lhandle->flags & ROAR_DL_FLAG_STATIC )
552   getsymhandle = ROAR_DL_HANDLE_DEFAULT;
553 }
554
555
556 if ( prefix != NULL ) {
557  roar_mm_strscpy(name, "_");
558  roar_mm_strscat(name, prefix);
559  roar_mm_strscat(name, _SUFFIX);
560 }
561
562 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): name='%s'", lhandle, prefix, name);
563
564 if ( (func = roar_dl_getsym(getsymhandle, name, -1)) == NULL ) {
565  ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s') = -1", lhandle, prefix);
566  return -1;
567 }
568
569 ROAR_DBG("roar_dl_ra_init(lhandle=%p, prefix='%s'): func=%p", lhandle, prefix, func);
570
571 lib = func(para);
572
573 if ( lib == NULL )
574  return -1;
575
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
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
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
603 if ( !((void*)lhandle < (void*)128) ) {
604  lhandle->lib = lib;
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);
621  if ( (void*)lhandle < (void*)128 ) {
622   *(lib->global_data_pointer) = lib->global_data_init;
623  } else {
624   *(lib->global_data_pointer) = lhandle->context.global_data;
625  }
626 }
627
628 for (i = 0; i < ROAR_DL_FN_MAX; i++) {
629  if ( lib->func[i] != NULL )
630   lib->func[i](para, lib);
631 }
632
633 if ( lib->global_data_pointer != NULL ) {
634  if ( !((void*)lhandle < (void*)128) ) {
635   *(lib->global_data_pointer) = global_data_state;
636  }
637 }
638
639 if ( !((void*)lhandle < (void*)128) )
640  lhandle->runtime_flags |= RTF_RA_INITED;
641
642 return 0;
643}
644
645const char * roar_dl_errstr(struct roar_dl_lhandle * lhandle) {
646#if defined(ROAR_HAVE_LIBDL)
647 (void)lhandle;
648 return dlerror();
649#elif defined(ROAR_TARGET_WIN32)
650 roar_err_from_errno();
651 return roar_error2str(roar_error);
652#else
653 return NULL;
654#endif
655}
656
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
703int                      roar_dl_context_restore(struct roar_dl_lhandle * lhandle) {
704 struct roar_error_state error_state;
705
706 ROAR_DBG("roar_dl_context_restore(lhandle=%p) = ?", lhandle);
707
708 if ( (void*)lhandle < (void*)128 ) {
709  ROAR_DBG("roar_dl_context_restore(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
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 ) {
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);
721  lhandle->context.global_data_state = *(lhandle->lib->global_data_pointer);
722  *(lhandle->lib->global_data_pointer) = lhandle->context.global_data;
723 }
724
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);
729 return 0;
730}
731
732int                      roar_dl_context_store(struct roar_dl_lhandle * lhandle) {
733 struct roar_error_state error_state;
734
735 ROAR_DBG("roar_dl_context_store(lhandle=%p) = ?", lhandle);
736
737 if ( (void*)lhandle < (void*)128 ) {
738  ROAR_DBG("roar_dl_context_store(lhandle=%p) = -1 // errno=NOTSUP", lhandle);
739  roar_err_set(ROAR_ERROR_NOTSUP);
740  return -1;
741 }
742
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
749 if ( lhandle->lib->global_data_pointer != NULL ) {
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);
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
759 ROAR_DBG("roar_dl_context_store(lhandle=%p) = 0", lhandle);
760 return 0;
761}
762
763int                      roar_dl_appsched_trigger(struct roar_dl_lhandle * lhandle, enum roar_dl_appsched_trigger trigger) {
764 int (*func)  (struct roar_dl_librarypara * para) = NULL;
765 int ret;
766
767 if ( (void*)lhandle < (void*)128 ) {
768  roar_err_set(ROAR_ERROR_NOTSUP);
769  return -1;
770 }
771
772 if ( lhandle->lib == NULL ) {
773  roar_err_set(ROAR_ERROR_TYPEMM);
774  return -1;
775 }
776
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 :             \
785    func = lhandle->lib->appsched->lname;       \
786   break;
787  _trig(init, INIT);
788  _trig(free, FREE);
789  _trig(update, UPDATE);
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
799 }
800
801 if ( func == NULL ) {
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  }
809  roar_err_set(ROAR_ERROR_NOENT);
810  return -1;
811 }
812
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
825 roar_dl_context_restore(lhandle);
826 ret = func(lhandle->para);
827 roar_dl_context_store(lhandle);
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
837 return ret;
838}
839
840//ll
Note: See TracBrowser for help on using the repository browser.