aboutsummaryrefslogtreecommitdiffstats
path: root/lib/erl_interface/src/README.internal
blob: c1f2d6863fada000e7ca82a6280fef209dd1b58e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
******************************************************************************
                                 General
******************************************************************************

There are two different interfaces, the old 'erl_interface' and 'ei'.
The old interface is to depend on the new one, not the other way arount.

Erl_interface should be "thread safe", i.e. you should be able to 
handle connections, convert data etc from different threads.

Ei should be "reentrant" or "async safe", i.e. no locks should be set
so that if an ei function is called inside an signal handler there
could be a deadlock.

VxWorks call the operating processes "tasks". These are to be handled the
same way as Unix threads, i.e. there can only be one C node for all tasks
using the old interface.

Try to keep the documented functions, variables and symbols in sync
between

 * Documentation

 * ei.h and erl_interface.h

 * prog/ei_fake_prog.c and prog/erl_fake_prog.c

From time to time do a

  % (cd src; gmake check)

(FIXME this check should be rewritten to a test case)


******************************************************************************
                               Directories
******************************************************************************

 * src/aux/

   Support files for configure described in the next section

 * src/legacy/

   Old erl_interface stuff  FIXME what about thread support etc....?

 * src/connect/

   Create nodes, connections, communication with the other node etc

 * src/decode/

   Simple decode functions

 * src/encode/

   Simple encode functions

 * src/epmd/

   Handle communication with epmd

 * src/registry/

   Key/value database with optional mnesia back up

 * src/misc/

   The rest of the library

 * src/prog/

   erl_call and some test programs for compiling and linking

 * src/not_used/

   Strange, some files are not used....


******************************************************************************
                      Configuration support files
******************************************************************************

The build uses GNU configure and libtool. The libtool and autoconf
package don't need to be installed to configure and build the
sources. But in "maintainer mode" you need them to update some files
in the source distribution.

 * configure.in 

   Used in maintainer mode together with "aclocal.m4" to create
   "configure". "configure.in" is hand written and only need to
   be updated when you change the sources to use new header files
   or C compiler features. You may get some hints about what to
   update using a recent autoconf package and do

     % cd erl_inteface
     % autoscan src

   The result to compare with the current "configure.in" will be
   stored in "src/configure.scan".

 * aclocal.m4

   This file contains macros generated by ??? appended
   with the content of "libtool.m4" in the installed libtool
   package. (FIXME don't know when this is to be updated and
   why it contains so much).

 * src/aux/config.guess
 * src/aux/config.sub

   Used by "configure" to form the subdirectory name
   "cpu-vendor-os".

 * src/aux/install-sh*

   Used if no other BSD compatible install script is found.

 * src/aux/config.h.in

   Used by "configure" as a template for the resulting
   "src/config.h". The file "config.h.in" should be
   updated when "configure.in" is updated because the
   new macros used in your source and this is the file
   where they are listed. You can find out what to update
   using

     % autoheader

 * ltmain.sh

   This is XXX (FIXME what?)

The base for the configure.in script was created with 'autoscan'.
The base for the config.h.in file was created with 'autoheader'.


******************************************************************************
                          Writing source
******************************************************************************

C files in "registry" are considered users of 'ei' and should not
include "eidef.h" or "config.h", only "ei.h".

C files in "prog" could include "config.h" directly.

Other C files should include "eidef.h" as the first line of
source. "eidef.h" contains some common constants and macros and
also includes config.h.

In general avoid including other header files from header files.
The exception is to make the protoypes complete to the user of
this library, i.e. to include <stdio.h> to defined FILE or
to include "ei_x_encode" to define the type ei_x_buff.

The function ei_decode_term() (FIXME encode_term?) work on ETERM,
i.e. it converts between the old erl_interface format and ei.
Because of this it is really part of the erl_interface library,
not the ei library.

Use uint8, uint16, uint32, int8, int16, and int32 for types
where size matters ;-) Use uint8 for buffers where we construct
messages.

NOTE!!!! Sending a "char" to macros like isupper(), isalpha() where
the character is > 127 will cause serios problems on some
machines/OS. The reason is that

   'char' may be unsigned, i.e. the Swedish char '�' will 
   as a number be negativ.

   The implementation of isupper() and others will on some
   machines use an array that is indexed with the incoming
   character code. The Swedish '�' will then create an access
   on memory outside the array!

This may give a random value as a result or a segmentation
violation error.


******************************************************************************
                          Global variables
******************************************************************************

There are two reasons we avoid global variables:

  - It is much easier to support threads without them

  - On operating systems like VxWorks the global variable is global
    to all operating system processes.

There are a few global variables that are ok

  ei_x_extra	         This is set to 100 in "ei_x_encode.c" but can be
                         changed for debugging the memory allocation.

  ei_trace_distribution  Enable verbose tracing on stderr.

  errno			 In the non threaded version of the lib this
			 is a global variable.

  __erl_errno 		 This is a global handled by "ei_pthreads.c"

You can check for globals using something like

  % nm -g ei_fake_prog | fgrep OBJT

Global variables but with local scope

  erl_if_ec              Global state, is ok


******************************************************************************
                           The "long long" story
******************************************************************************

There are some functions in the 'ei' library that uses the GCC and
VC++ "long long" type. Unfortunately this can lead to some trouble.

When user code is linked with the "libei.a" the linker will extract
all objects files needed for resolving all symbol referenses
found. This means that you want to follow the rule that

 * To reduce executable code size we use resonably small C source
   files. One C file is one object file.

 * We try to avoid unessesary dependency. For example currently almost all
   ei_x_encode*() functions are in the same object file. Because they all
   use the corresponding ei_encode*() function this means using one ei_x
   function we will link in "ei_x_encode.o" object file but also all the
   "ei_encode*.o" object files even if they are not used.

But the above is not the real trouble, memory and disk is cheap these
days.  The real trouble is if we compile the 'ei' library using one
compiler, usually GNU cc, and link with another linker than GNU ld or
miss some runtime libraries that the GNU cc generated object files
assume is on the target. For example currently on Solaris some "long
long" operations will create a dependency to a "hidden" library
"libgcc.a". For example in a library not released got references to
"libgcc.a" '__ashldi3'

   % nm -A libei.a | grep '__ashldi3'
   libei.a[decode_longlong.o]: [6]  | 0| 0|NOTY |GLOB |0 |UNDEF |__ashldi3
   libei.a[decode_ulonglong.o]: [5] | 0| 0|NOTY |GLOB |0 |UNDEF |__ashldi3

We can accept that a dependecy is created for code linked with
"libei.a" that actually use 'ei' long long functions. But if we
arrange the 'ei' source badly using a non "long long" functions from
'ei' will still link in an object file that need "libgcc.a". One
example is that in plain R9C the ei_x_encode_longlong() function is
located in the file "ei_x_encode.c". So if any "long long" ei_x
function is used we have an unessesary dependency on
"ei_encode_longlong.o" and then need to link with GNU ld on with the
user code or explicitely link with "libgcc.a". The situation can be
visible in in plain R9C using

     % nm -A erl_interface-3.4/lib/libei.a | \
	  grep 'longlong' | fgrep -v 'longlong.o'

As an possibly alternative to the current solution we may include the
object files inside the "libgcc.a" archive in the "libei.a" archive.
The "libgcc.a" that is assumed to be used when linking can be found
using

  % gcc -print-libgcc-file-name

Some links about problems and solutions using "libgcc.a"

  http://www.gnu.org/software/gcc/gcc-3.0/libgcc.html
  http://www.gnu.org/software/libc/FAQ.html

The license for "libgcc.a" is a bit special and not located on the
official sites. You have to look in the source file for the "libgcc.a"
you use. The file is named "libgcc.c". If you don't know what gcc that
was used for the build of for example 'r9c' you can use

  % otp_build_env -o r9c | perl -ne '/(gcc-[\d\.]+)/ and print "$1\n"'

Then to view the lincense do

  % less `find /usr/local/share/src/gcc-REL/ -name "libgcc*.c"`


********************************* EOF ****************************************