[C/C++] func() vs. func(void)

In C, func() and func(void) have different function signature.
(But, in C++, these two are same.)

‘func()’ means ‘this function can have any number of arguments (0 ~ infinite)’.
But, ‘func(void)’ means ‘this function doesn’t have argument.’
See following example.

#ifdef CASE1
void func(void); /* (1) */
#else
void func();     /* (2) */
#endif

void
func(int i) {
        ; /* do something */
}

If ‘CASE1’ is defined, compiling this file complains error like “error: conflicting types for ‘func'”.
But, ‘CASE1’ is not defined, this is well-compiled.
Now, you can clearly understand difference.

So, using ‘func(void)’ is better for readibility if ‘func’ really doesn’t have any arguement, instead of just ‘func()’.

*** One more. ***
In C, ‘extern’ for function is default visibility.
So, in function declaration, ‘extern void func(void);’ is exactly same with ‘void func(void);’.
Therefore any of them is OK.
( [ omitting ‘extern’ for simplicity ] vs. [ using ‘extern’ to increase readability ] )
But, default visibility of function depends on compiler.
For portability reason, using macro is usually better instead of using explicit directive – especially at shared library header.
(Ex. ‘EXTERN void func(void)’)

Advertisements

[Android] Creating minimum set of Android (Kernel + adbd + ueventd) for Android kernel test.

To test Android kernel, keeping minimum number of user space process is very useful.
Actually, ‘adbd’ and ‘ueventd’ is enough on Android.
Here is the way how to make device have only minimum user space processes – adbd and ueventd.
Followings are file structure of ramdisk image.

[ Create ramdisk ]

let’s make following directory structure in ramdisk.

/bin -> sbin
/sbin -+- busybox
       +- adbd
       +- ueventd -> ../init
       +- <...> -> busybox
/init
/init.rc
/default.prop

All are same with default android except that busybox is in /sbin and /bin is symbolic link to /sbin.
Let’s look into one by one.

/init : same binary with default Android.
/bin : symbolic link to /sbin.
/default.prop : same with default Android. – adb and debugging is enabled.
/sbin/busybox : statically linked busybox.
/sbin/… : tools (symbolic link to busybox). Ex, sh -> busybox, ls -> busybox.
/sbin/adbd :
Modified adbd. Original adbd uses /system/bin/sh as its terminal shell. But, this one uses /bin/sh.
To do this, value of SHELL_COMMAND at system/core/adb/service.c should be modified.
/init.rc :
Simplified one. Only adbd and ueventd is started.
One important note is, “DO NOT make empty section(ex. on fs)!”. This will lead init process to error and system will restarted again and again.
Here is sample.

on early-init
    start ueventd

on init
    sysclktz 0
    export PATH /bin:/sbin:

#on fs

#on post-fs

#on post-fs-data

on boot
   start adbd

## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd

service adbd /sbin/adbd

[ Make ramdisk image ]

Let’s assume that current working directory is ramdisk directory.

find . | cpio -o -H newc | gzip > newramdisk.gz

This newly generated gzip file can be renamed directly to ramdisk.img.

[ Make boot image ]

mkbootimg tool is used. This can be easily found at out/host/<arch>/bin after building android from source.

mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel <zImage file> --ramdisk <ramdisk image> -o newboot

[ Verify ]

After flashing newly generated boot image, reboot device.
The only respond that device can do, is done at boot-loader stage. After that device doesn’t anything.
After waiting some moments, try adb device. Then host PC can find the device and adb shell can be used.
Type adb shell ps. Then, you can check that only three user space process are running – init, adbd and ueventd.

[ Debugging ]

Except for kernel, adbd and init may be required to be modified (As mentioned above, modified adbd is used.). Printing log is very helpful for debugging and using framebuffer console is simple way to do this.
Here is the step (ex. adbd).

* comment out xxxx in init.c
=> this removes /dev/console (framebuffer console)
* modify start_logging() and start_device_log() in adb.c.
=> use /dev/console as stdout and stderr file.

Now, log message of adbd will be shown on the framebuffer (that is, displayed at the panel.)

[ Something more ]

You may build your own Linux environment on the device by building file system and installing libraries etc.
In my case, I set up tools for development – ex. glibc, gcc, binutils etc, and compiled LTP(Linux Test Project) to test kernel.
Enjoy your minimum Android environment :-).

[C/C++] Tips for OOP – module initialization.

OOP SW design is usually compose of one main control routine (henceforth MCR) and lots of sub modules.
But, MCR don’t need to (must not need to) know inside implementation of every sub modules.
Sometimes, MCR don’t need to know even existence of some sub modules.
The problem is, most sub modules require initialization.
How can sub modules whose existence is now known, be initialized.
Due to this issue, principle of information hiding is sometimes broken.
Let’s see below example.

FILE : main.c
-------------
int main(int argc, char* argv[]) {
        ...

}

FILE : moduleA.c
----------------
...

FILE : moduleB.c
----------------
...

Assume that, each module requires initialization and main.c don’t need to know existence of each module.
How can we resolve this issue?
Easiest way is calling initialization function of each module with damaging principle of information hiding little bit, like mentioned above.

FILE : main.c
-------------
extern void moduleA_init();
extern void moduleB_init();

int main(int argc, char* argv[]) {
        ...
        moduleA_init();
        moduleB_init();
        ...
}

FILE : moduleA.c
----------------
...
void moduleA_init() { ... }

FILE : moduleB.c
----------------
...
void moduleB_init() { ... }

At above code, main.c becomes to know existence of moduleA and moduleB.
That is, in terms of modules, principle of information hiding is damaged although it’s very little.
Additionally, global symbol space is dirtier.
Regarding maintenance, whenever new module is added, modifying main.c is unavoidable.
But, main.c doesn’t have any dependency on newly added module.
With this and that, this way is uncomfortable.
How can we clean up these?
Using constructor leads us to better way.

Functions in constructor are executed before main function.
So, it is very useful for this case.
Easiest way is setting every initialization function as constructor.
But, in this case, we cannot control the moment when module is initialized at.
Therefore, it is better that each module’s initialization function is registered to MCR, and MCR calls these registered function at right moment.
Following pseudo code is simple implementation of this concept.

FILE : main.c
-------------
void register_initfn(void (*fn)()) {
        list_add(initfn_list, fn);
}

int main(int argc, char* argv[]) {
        ...
        /* initialize modules */
        foreach(initfn_list, fn)
                (*fn)();
        ...
}

FILE : module.h
---------------
extern void register_initfn(void (*fn)());
#define MODULE_INITFN(fn)                               \
        static void __##fn##__() __attribute__ ((constructor)); \
        static void __##fn##__() { register_initfn(&fn); }

FILE : moduleA.c
----------------
...
#include "module.h"
...
static void _myinit() { ... }
MODULE_INITFN(_myinit)

FILE : moduleB.c
----------------
...
#include "module.h"
...
static void _myinit() { ... }
MODULE_INITFN(_myinit)

Now, MCR don’t need to know existence of each modules.
And, MCR can also control the moment of each module’s initialization.
In addition, adding new module doesn’t require any modification of MCR side.
It is closer to OOP’s concept, isn’t it?

We can improve this concept by customizing memory section.
Here is rough description of this.

* Declare special memory section for initializer function.
    - In gcc, ld script should be modified.

* Put initializer function into this section.
    - __attribute__ ((__section__("xxxx"))) can be used.

* MCR can read this section and call these functions at appropriate moment.

Actually, this way is better than using constructor in terms of SW design.
Linux kernel uses this concept in it’s driver model.
(For deeper analysis, kernel source code can be good reference.)
But, in many cases, using this concept may lead to over-engineering.
So, if there isn’t any other concern, using constructor is enough.

[Prog] Separating mechanism from policy (microscopical view) – function implementation.

Separating mechanism from policy is very important issue of SW design.
This is also true for microscopic area – implementing function.
Here is one of simplest example – function that calculates area of rectangle.

int rect_area(int left, int top, int right, int bottom) {
        return (right - left) * (bottom - top);
}

Simple, isn’t it?
But, this function doesn’t have any exception/error handling.
Let’s add some of them.

int rect_area(int left, int top, int right, int bottom) {
        if (left >= right)
                left = right;
        if (top >= bottom)
                top = bottom;
        return (right - left) * (bottom - top);
}

It’s seems good.
Soon after, another function that calculates area of rectangle is needed.
But, this function should return error value if input rectangle is invalid.
I think quick solution is

int rect_area2(int left, int top, int right, int bottom) {
        if (left > right || top > bottom)
                return -1;
        return (right - left) * (bottom - top);
}

But, in this solution, code for calculating area of rectangle is duplicated.
At above example, this is just one-line code. So, duplicating is not a big deal.
But, it’s not good in terms of code structure.
Why did this happen?
Calculating rectangle area is ‘Mechanism’.
But, exception/error handling is ‘Policy’ at this example.
So, above example should be implemented like below.

static inline int _rect_area(int left, int top, int right, int bottom) {
        return (right - left) * (bottom - top);
}

int rect_area(int left, int top, int right, int bottom) {
        if (left >= right)
                left = right;
        if (top >= bottom)
                top = bottom;
        return _rect_area(left, top, right, bottom);
}
int rect_area2(int left, int top, int right, int bottom) {
        if (left > right || top > bottom)
                return -1;        
        return _rect_area(left, top, right, bottom);
}

Can you know the difference?
‘_rect_area’ is implementation of pure ‘Mechanism’.
And policy is implemented at each interface function.
Even for simple function, developer should consider CONCEPT of separating Mechanism from Policy.

[ARM] Multi-core optimzation test…

This test is done under following environment.

x86 :

intel Core(TM)2 Duo T9400 2.53Mhz
GCC-4.4.5

ARM :

OMAP4430 (Cortax-A9)
Android NDK platform 9

Test code.

/*
 * Test Configuration
 */
#define _ARRSZ    1024*1024*8

static int _arr[_ARRSZ];

static void
_init() {
    int i;
    for (i = 0; i < _ARRSZ; i++)
        _arr[i] = i;
}

static unsigned long long
_utime() {
    struct timeval tv;
    if (gettimeofday(&tv, NULL))
        assert(0);
    return (unsigned long long)(tv.tv_sec * 1000000)
        + (unsigned long long)tv.tv_usec;
}

#define _test_arraycopy_pre()               \
    int  i;                                 \
    unsigned long long ut;                  \
    int* ia = malloc(_ARRSZ * sizeof(*ia));

#define _test_arraycopy_post()              \
    free(ia);

#define _operation()            \
    do {                        \
        ia[i] = _arr[i];        \
    } while (0)

static void*
_test_arraycopy_worker(void* arg) {
    int     i;
    int*    ia = arg;
    for (i = (_ARRSZ / 2); i < _ARRSZ; i++)
        _operation();
    return NULL;
}

static unsigned long long
_test_arraycopy_sc() {
    _test_arraycopy_pre();

    ut = _utime();
    for (i = 0; i < _ARRSZ; i++)
        _operation();
    ut = _utime() - ut;

    _test_arraycopy_post();

    return ut;
}

static unsigned long long
_test_arraycopy_dc() {
    pthread_t thd;
    void*     ret;
    _test_arraycopy_pre();

    ut = _utime();
    if (pthread_create(&thd,
               NULL,
               &_test_arraycopy_worker,
               (void*)ia))
        assert(0);

    for (i = 0; i < (_ARRSZ / 2); i++)
        _operation();

    if (pthread_join(thd, &ret))
        assert(0);

    ut = _utime() - ut;

    _test_arraycopy_post();

    return ut;
}

#undef _test_arraycopy_pre
#undef _test_arraycopy_post

int
main(int argc, char* argv[]) {
    _init();
    printf(">> SC : %lld ", _test_arraycopy_sc());
    printf(">> DC : %lld\n", _test_arraycopy_dc());
    return 0;
}

[Test 1]
x86

>> SC : 59346 >> DC : 38566
>> SC : 59195 >> DC : 39028
>> SC : 49529 >> DC : 38160
>> SC : 49722 >> DC : 38457
>> SC : 49952 >> DC : 37457

ARM

>> SC : 102295 >> DC : 94147
>> SC : 102264 >> DC : 94025
>> SC : 102173 >> DC : 94116
>> SC : 102172 >> DC : 94116
>> SC : 102325 >> DC : 94177

Change ‘_operation’ macro to as follows

#define _operation()                                    \
    do {                                                \
        if (i > _ARRSZ / 2)                             \
            ia[i] = (_arr[i] & 0xff) << 8 ^ _arr[i];    \
        else                                            \
            ia[i] = (_arr[i] & 0xff) << 16 ^ _arr[i];   \
    } while (0)                                         \

[Test 2]
x86

>> SC : 60696 >> DC : 40523
>> SC : 56907 >> DC : 45355
>> SC : 55066 >> DC : 42329
>> SC : 54931 >> DC : 40651
>> SC : 57022 >> DC : 41879

ARM

>> SC : 164514 >> DC : 112671
>> SC : 163971 >> DC : 112854
>> SC : 164521 >> DC : 112976
>> SC : 163940 >> DC : 112732
>> SC : 164245 >> DC : 112671

Interesting result, isn’t it?
For heavily-memory-accessing-code (Test 1), ARM does not show good statistics for multi-core (in this case, dual-core) optimization.
But, if not (Test 2), optimization shows quite good results.
And, x86 seems to handle memory accessing from multi-core, quite well.

So, developers should consider ARM’s characteristic when optimize codes for multi-core.
(I’m sure that ARM will improve this someday! :-) )

* Things to consider regarding this kind of optimization *
Cache, Cache coherence, Memory Controller, Bus etc…

[ Test for later version of ARM (ex Cortax-A15) will be listed continuously… ]

[Android] Managing service…

Service
——-
init process 는 다음을 통해서 각종 service를 control함.

SIGCHLD signal handler를 정의해서, service의 상태를 파악함
service가 죽는 경우 SIGCHLD signal이 날아오고, 이 signal로 어떤 service가 죽었는지/시작했는지 파악하고, 각 service의 flag에 따라서 다음 행동 (해당 service를 다시 시작하거나, system을 restart하거나 (critical service))을 결정함.
[property_service.c] ‘/dev/socket/property_service’ socket을 열고 message를 기다림 (PROP_SERVICE_NAME).
‘property_set(…)’ interface를 통해서, property_service socket에 message가 써지고, init process의 property service부분에서 이 message를 handling함.
‘ctl.start/stop/restart’ 는 source code에 hard-coded된 특수한 message로, 해당 이름의 service를 control한다.

잊어먹지 않기 위해서 일단 기록해 둠….