~ubuntu-branches/ubuntu/trusty/erlang/trusty

« back to all changes in this revision

Viewing changes to erts/emulator/test/nif_SUITE_data/nif_mod.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2011-05-05 15:48:43 UTC
  • mfrom: (3.5.13 sid)
  • Revision ID: james.westby@ubuntu.com-20110505154843-0om6ekzg6m7ugj27
Tags: 1:14.b.2-dfsg-3ubuntu1
* Merge from debian unstable.  Remaining changes:
  - Drop libwxgtk2.8-dev build dependency. Wx isn't in main, and not
    supposed to.
  - Drop erlang-wx binary.
  - Drop erlang-wx dependency from -megaco, -common-test, and -reltool, they
    do not really need wx. Also drop it from -debugger; the GUI needs wx,
    but it apparently has CLI bits as well, and is also needed by -megaco,
    so let's keep the package for now.
  - debian/patches/series: Do what I meant, and enable build-options.patch
    instead.
* Additional changes:
  - Drop erlang-wx from -et
* Dropped Changes:
  - patches/pcre-crash.patch: CVE-2008-2371: outer level option with
    alternatives caused crash. (Applied Upstream)
  - fix for ssl certificate verification in newSSL: 
    ssl_cacertfile_fix.patch (Applied Upstream)
  - debian/patches/series: Enable native.patch again, to get stripped beam
    files and reduce the package size again. (build-options is what
    actually accomplished this)
  - Remove build-options.patch on advice from upstream and because it caused
    odd build failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * %CopyrightBegin%
 
3
 *
 
4
 * Copyright Ericsson AB 2009-2010. All Rights Reserved.
 
5
 *
 
6
 * The contents of this file are subject to the Erlang Public License,
 
7
 * Version 1.1, (the "License"); you may not use this file except in
 
8
 * compliance with the License. You should have received a copy of the
 
9
 * Erlang Public License along with this software. If not, it can be
 
10
 * retrieved online at http://www.erlang.org/.
 
11
 *
 
12
 * Software distributed under the License is distributed on an "AS IS"
 
13
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
14
 * the License for the specific language governing rights and limitations
 
15
 * under the License.
 
16
 *
 
17
 * %CopyrightEnd%
 
18
 */
1
19
#include "erl_nif.h"
2
20
#include <string.h>
3
 
#include <assert.h>
 
21
#include <stdio.h>
4
22
 
5
23
#include "nif_mod.h"
6
24
 
 
25
#define CHECK(X) ((void)((X) || (check_abort(__LINE__),1)))
 
26
#ifdef __GNUC__
 
27
static void check_abort(unsigned line) __attribute__((noreturn));
 
28
#endif
 
29
static void check_abort(unsigned line)
 
30
{
 
31
    enif_fprintf(stderr, "Test CHECK failed at %s:%u\r\n",
 
32
            __FILE__, line);
 
33
    abort();
 
34
}
7
35
 
8
36
static int static_cntA; /* zero by default */
9
37
static int static_cntB = NIF_LIB_VER * 100;
10
38
 
11
 
static void add_call(ErlNifEnv* env, NifModPrivData* data, const char* func_name)
12
 
{
13
 
    CallInfo* call = enif_alloc(env, sizeof(CallInfo)+strlen(func_name));
 
39
static ERL_NIF_TERM am_true;
 
40
static ERL_NIF_TERM am_null;
 
41
static ERL_NIF_TERM am_resource_type;
 
42
static ERL_NIF_TERM am_resource_dtor_A;
 
43
static ERL_NIF_TERM am_resource_dtor_B;
 
44
 
 
45
static NifModPrivData* priv_data(ErlNifEnv* env)
 
46
{
 
47
    return (NifModPrivData*) enif_priv_data(env);
 
48
}
 
49
 
 
50
static void init(ErlNifEnv* env)
 
51
{
 
52
    am_true = enif_make_atom(env, "true");
 
53
    am_null = enif_make_atom(env, "null");
 
54
    am_resource_type = enif_make_atom(env, "resource_type");
 
55
    am_resource_dtor_A = enif_make_atom(env, "resource_dtor_A");
 
56
    am_resource_dtor_B = enif_make_atom(env, "resource_dtor_B");
 
57
}
 
58
 
 
59
static void add_call_with_arg(ErlNifEnv* env, NifModPrivData* data, const char* func_name,
 
60
                              const char* arg, int arg_sz)
 
61
{
 
62
    CallInfo* call = (CallInfo*)enif_alloc(sizeof(CallInfo)+strlen(func_name) + arg_sz);
14
63
    strcpy(call->func_name, func_name);
15
64
    call->lib_ver = NIF_LIB_VER;
16
65
    call->static_cntA = ++static_cntA;
17
66
    call->static_cntB = ++static_cntB;
 
67
    call->arg_sz = arg_sz;
 
68
    if (arg != NULL) {
 
69
        call->arg = call->func_name + strlen(func_name) + 1;
 
70
        memcpy(call->arg, arg, arg_sz);
 
71
    }
 
72
    else {
 
73
        call->arg = NULL;
 
74
    }
 
75
    enif_mutex_lock(data->mtx);
18
76
    call->next = data->call_history;
19
77
    data->call_history = call;
20
 
}
21
 
 
22
 
#define ADD_CALL(FUNC_NAME) add_call(env, enif_get_data(env),FUNC_NAME)
23
 
 
24
 
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
25
 
{
26
 
    NifModPrivData* data = enif_alloc(env, sizeof(NifModPrivData));
27
 
    assert(data != NULL);
 
78
    enif_mutex_unlock(data->mtx);
 
79
}
 
80
 
 
81
static void add_call(ErlNifEnv* env, NifModPrivData* data,const char* func_name)
 
82
{
 
83
    add_call_with_arg(env, data, func_name, NULL, 0);
 
84
}
 
85
 
 
86
#define ADD_CALL(FUNC_NAME) add_call(env, priv_data(env),FUNC_NAME)
 
87
 
 
88
#define STRINGIFY_(X) #X
 
89
#define STRINGIFY(X) STRINGIFY_(X)
 
90
 
 
91
static void resource_dtor_A(ErlNifEnv* env, void* a)
 
92
{
 
93
    const char dtor_name[] = "resource_dtor_A_v"  STRINGIFY(NIF_LIB_VER); 
 
94
 
 
95
    add_call_with_arg(env, priv_data(env), dtor_name, (const char*)a,
 
96
                      enif_sizeof_resource(a));
 
97
}
 
98
 
 
99
static void resource_dtor_B(ErlNifEnv* env, void* a)
 
100
{
 
101
    const char dtor_name[] = "resource_dtor_B_v"  STRINGIFY(NIF_LIB_VER);
 
102
 
 
103
    add_call_with_arg(env, priv_data(env), dtor_name, (const char*)a,
 
104
                      enif_sizeof_resource(a));
 
105
}
 
106
 
 
107
/* {resource_type, Ix|null, ErlNifResourceFlags in, "TypeName", dtor(A|B|null), ErlNifResourceFlags out}*/
 
108
static void open_resource_type(ErlNifEnv* env, ERL_NIF_TERM op_tpl)
 
109
{
 
110
    NifModPrivData* data = priv_data(env);
 
111
    const ERL_NIF_TERM* arr;
 
112
    int arity;
 
113
    char rt_name[30];
 
114
    union { ErlNifResourceFlags e; int i; } flags, exp_res, got_res;
 
115
    unsigned ix;
 
116
    ErlNifResourceDtor* dtor;
 
117
    ErlNifResourceType* got_ptr;
 
118
 
 
119
    CHECK(enif_get_tuple(env, op_tpl, &arity, &arr));
 
120
    CHECK(arity == 6);
 
121
    CHECK(enif_is_identical(arr[0], am_resource_type));
 
122
    CHECK(enif_get_int(env, arr[2], &flags.i));
 
123
    CHECK(enif_get_string(env, arr[3], rt_name, sizeof(rt_name), ERL_NIF_LATIN1) > 0);
 
124
    CHECK(enif_get_int(env, arr[5], &exp_res.i));
 
125
        
 
126
    if (enif_is_identical(arr[4], am_null)) {
 
127
        dtor = NULL;
 
128
    }
 
129
    else if (enif_is_identical(arr[4], am_resource_dtor_A)) {
 
130
        dtor = resource_dtor_A;
 
131
    }
 
132
    else {
 
133
        CHECK(enif_is_identical(arr[4], am_resource_dtor_B));
 
134
        dtor = resource_dtor_B;
 
135
    }
 
136
 
 
137
    got_ptr = enif_open_resource_type(env, NULL, rt_name, dtor,
 
138
                                      flags.e, &got_res.e);
 
139
 
 
140
    if (enif_get_uint(env, arr[1], &ix) && ix < RT_MAX && got_ptr != NULL) {
 
141
        data->rt_arr[ix] = got_ptr;
 
142
    }
 
143
    else {
 
144
        CHECK(enif_is_identical(arr[1], am_null));
 
145
        CHECK(got_ptr == NULL);
 
146
    }
 
147
    CHECK(got_res.e == exp_res.e);
 
148
}
 
149
 
 
150
static void do_load_info(ErlNifEnv* env, ERL_NIF_TERM load_info)
 
151
{
 
152
    NifModPrivData* data = priv_data(env);
 
153
    ERL_NIF_TERM head, tail;
 
154
    unsigned ix;
 
155
    for (ix=0; ix<RT_MAX; ix++) {
 
156
        data->rt_arr[ix] = NULL;
 
157
    }
 
158
    for (head = load_info; enif_get_list_cell(env, head, &head, &tail);
 
159
          head = tail) {
 
160
 
 
161
        open_resource_type(env, head);  
 
162
    }    
 
163
    CHECK(enif_is_empty_list(env, head));
 
164
}
 
165
 
 
166
static int load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
 
167
{
 
168
    NifModPrivData* data;
 
169
 
 
170
    init(env);
 
171
    data = (NifModPrivData*) enif_alloc(sizeof(NifModPrivData));
 
172
    CHECK(data != NULL);
 
173
    *priv = data;
 
174
    data->mtx = enif_mutex_create("nif_mod_priv_data"); 
28
175
    data->ref_cnt = 1;
29
176
    data->call_history = NULL;
 
177
 
30
178
    add_call(env, data, "load");
31
179
 
32
 
    data->calls = 0;
33
 
    *priv_data = data;
34
 
    return 0;
35
 
}
36
 
 
37
 
static int reload(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
38
 
{
39
 
    add_call(env, *priv_data, "reload");
40
 
    return 0;
41
 
}
42
 
 
43
 
static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)
44
 
{
45
 
    NifModPrivData* data = *old_priv_data;
 
180
    do_load_info(env, load_info);
 
181
    data->calls = 0;    
 
182
    return 0;
 
183
}
 
184
 
 
185
static int reload(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
 
186
{
 
187
    NifModPrivData* data = (NifModPrivData*) *priv;
 
188
    init(env);
 
189
    add_call(env, data, "reload");
 
190
    
 
191
    do_load_info(env, load_info);
 
192
    return 0;
 
193
}
 
194
 
 
195
static int upgrade(ErlNifEnv* env, void** priv, void** old_priv_data, ERL_NIF_TERM load_info)
 
196
{
 
197
    NifModPrivData* data = (NifModPrivData*) *old_priv_data;
 
198
    init(env);
46
199
    add_call(env, data, "upgrade");
47
200
    data->ref_cnt++;
48
 
    *priv_data = *old_priv_data;    
 
201
 
 
202
    *priv = *old_priv_data;    
 
203
    do_load_info(env, load_info);
 
204
    
49
205
    return 0;
50
206
}
51
207
 
52
 
static void unload(ErlNifEnv* env, void* priv_data)
 
208
static void unload(ErlNifEnv* env, void* priv)
53
209
{
54
 
    NifModPrivData* data = priv_data;
 
210
    NifModPrivData* data = (NifModPrivData*) priv;
 
211
    int is_last;
55
212
    add_call(env, data, "unload");
56
 
    if (--data->ref_cnt == 0) {
57
 
        enif_free(env, data);
58
 
    }
 
213
    NifModPrivData_release(data);
59
214
}
60
215
 
61
 
static ERL_NIF_TERM lib_version(ErlNifEnv* env)
 
216
static ERL_NIF_TERM lib_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
62
217
{
63
218
    ADD_CALL("lib_version");
64
219
    return enif_make_int(env, NIF_LIB_VER);
65
220
}
66
221
 
67
 
static ERL_NIF_TERM call_history(ErlNifEnv* env)
68
 
{
69
 
    NifModPrivData* data = (NifModPrivData*) enif_get_data(env);
70
 
    ERL_NIF_TERM list = enif_make_list(env, 0); /* NIL */
71
 
 
72
 
    while (data->call_history != NULL) {
73
 
        CallInfo* call = data->call_history;
74
 
        ERL_NIF_TERM tpl = enif_make_tuple(env, 2, 
75
 
                                           enif_make_atom(env,call->func_name),
76
 
                                           enif_make_int(env,call->lib_ver));
77
 
        list = enif_make_list_cell(env, tpl, list);
78
 
        data->call_history = call->next;
79
 
        enif_free(env,call);
80
 
    }
81
 
    return list;
82
 
}
83
 
 
84
 
static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env)
 
222
static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
85
223
{
86
224
    ADD_CALL("get_priv_data_ptr");
87
 
    return enif_make_ulong(env, (unsigned long)enif_get_data(env));
88
 
}
89
 
 
 
225
    return enif_make_ulong(env, (unsigned long)priv_data(env));
 
226
}
 
227
 
 
228
static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 
229
{
 
230
    NifModPrivData* data = priv_data(env);
 
231
    ErlNifBinary ibin;
 
232
    char* a;
 
233
    ERL_NIF_TERM ret;
 
234
    unsigned ix;
 
235
    if (!enif_get_uint(env, argv[0], &ix) || ix >= RT_MAX 
 
236
        || !enif_inspect_binary(env, argv[1], &ibin)) {
 
237
        return enif_make_badarg(env);
 
238
    }
 
239
    a = (char*) enif_alloc_resource(data->rt_arr[ix], ibin.size);
 
240
    memcpy(a, ibin.data, ibin.size);
 
241
    ret = enif_make_resource(env, a);
 
242
    enif_release_resource(a);
 
243
    return ret;
 
244
}
 
245
 
 
246
static ERL_NIF_TERM get_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 
247
{
 
248
    NifModPrivData* data = priv_data(env);
 
249
    ErlNifBinary obin;
 
250
    unsigned ix;
 
251
    void* a;
 
252
    if (!enif_get_uint(env, argv[0], &ix) || ix >= RT_MAX 
 
253
        || !enif_get_resource(env, argv[1], data->rt_arr[ix], &a)
 
254
        || !enif_alloc_binary(enif_sizeof_resource(a), &obin)) { 
 
255
        return enif_make_badarg(env);
 
256
    }
 
257
    memcpy(obin.data, a, obin.size);
 
258
    return enif_make_binary(env, &obin);
 
259
}
90
260
 
91
261
static ErlNifFunc nif_funcs[] =
92
262
{
93
263
    {"lib_version", 0, lib_version},
94
 
    {"call_history", 0, call_history},
95
 
    {"get_priv_data_ptr", 0, get_priv_data_ptr}
 
264
    {"get_priv_data_ptr", 0, get_priv_data_ptr},
 
265
    {"make_new_resource", 2, make_new_resource},
 
266
    {"get_resource", 2, get_resource}
96
267
};
97
268
 
98
269
#if NIF_LIB_VER != 3