diff options
Diffstat (limited to 'lib/kernel/src/erl_ddll.erl')
-rw-r--r-- | lib/kernel/src/erl_ddll.erl | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/lib/kernel/src/erl_ddll.erl b/lib/kernel/src/erl_ddll.erl new file mode 100644 index 0000000000..88f91de24f --- /dev/null +++ b/lib/kernel/src/erl_ddll.erl @@ -0,0 +1,150 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% Dynamic Driver Loader and Linker +%% +%% Interface for dynamic library/shared object driver loader/linker. +%% Provides methods for loading, unloading and listing drivers. + +-module(erl_ddll). + +-export([load_driver/2, load/2, + unload_driver/1, unload/1, reload/2, reload_driver/2, + format_error/1,info/1,info/0, start/0, stop/0]). + +%%---------------------------------------------------------------------------- + +-spec start() -> {'error', {'already_started', 'undefined'}}. + +start() -> + {error, {already_started,undefined}}. + +-spec stop() -> 'ok'. + +stop() -> + ok. + +-spec load_driver(Path :: string() | atom(), Driver :: string() | atom()) -> + 'ok' | {'error', any()}. + +load_driver(Path, Driver) -> + do_load_driver(Path, Driver, [{driver_options,[kill_ports]}]). + +-spec load(Path :: string() | atom(), Driver :: string() | atom()) -> + 'ok' | {'error', any()}. + +load(Path, Driver) -> + do_load_driver(Path, Driver, []). + +do_load_driver(Path, Driver, DriverFlags) -> + case erl_ddll:try_load(Path, Driver,[{monitor,pending_driver}]++DriverFlags) of + {error, inconsistent} -> + {error,bad_driver_name}; % BC + {error, What} -> + {error,What}; + {ok, already_loaded} -> + ok; + {ok,loaded} -> + ok; + {ok, pending_driver, Ref} -> + receive + {'DOWN', Ref, driver, _, load_cancelled} -> + {error, load_cancelled}; + {'UP', Ref, driver, _, permanent} -> + {error, permanent}; + {'DOWN', Ref, driver, _, {load_failure, Failure}} -> + {error, Failure}; + {'UP', Ref, driver, _, loaded} -> + ok + end + end. + +do_unload_driver(Driver,Flags) -> + case erl_ddll:try_unload(Driver,Flags) of + {error,What} -> + {error,What}; + {ok, pending_process} -> + ok; + {ok, unloaded} -> + ok; + {ok, pending_driver} -> + ok; + {ok, pending_driver, Ref} -> + receive + {'UP', Ref, driver, _, permanent} -> + {error, permanent}; + {'UP', Ref, driver, _, unload_cancelled} -> + ok; + {'DOWN', Ref, driver, _, unloaded} -> + ok + end + end. + +-spec unload_driver(Driver :: string() | atom()) -> 'ok' | {'error', any()}. + +unload_driver(Driver) -> + do_unload_driver(Driver,[{monitor,pending_driver},kill_ports]). + +-spec unload(Driver :: string() | atom()) -> 'ok' | {'error', any()}. + +unload(Driver) -> + do_unload_driver(Driver,[]). + +-spec reload(Path :: string() | atom(), Driver :: string() | atom()) -> + 'ok' | {'error', any()}. + +reload(Path,Driver) -> + do_load_driver(Path, Driver, [{reload,pending_driver}]). + +-spec reload_driver(Path :: string() | atom(), Driver :: string() | atom()) -> + 'ok' | {'error', any()}. + +reload_driver(Path,Driver) -> + do_load_driver(Path, Driver, [{reload,pending_driver}, + {driver_options,[kill_ports]}]). + +-spec format_error(Code :: atom()) -> string(). + +format_error(Code) -> + case Code of + % This is the only error code returned only from erlang code... + % 'permanent' has a translation in the emulator, even though the erlang code uses it to... + load_cancelled -> + "Loading was cancelled from other process"; + _ -> + erl_ddll:format_error_int(Code) + end. + +-spec info(Driver :: string() | atom()) -> [{atom(), any()}]. + +info(Driver) -> + [{processes, erl_ddll:info(Driver,processes)}, + {driver_options, erl_ddll:info(Driver,driver_options)}, + {port_count, erl_ddll:info(Driver,port_count)}, + {linked_in_driver, erl_ddll:info(Driver,linked_in_driver)}, + {permanent, erl_ddll:info(Driver,permanent)}, + {awaiting_load, erl_ddll:info(Driver,awaiting_load)}, + {awaiting_unload, erl_ddll:info(Driver,awaiting_unload)}]. + +-spec info() -> [{string(), [{atom(), any()}]}]. + +info() -> + {ok,DriverList} = erl_ddll:loaded_drivers(), + [{X,Y} || X <- DriverList, + Y <- [catch info(X)], + is_list(Y), not lists:member({linked_in_driver,true},Y)]. |