View Issue Details

IDProjectCategoryView StatusLast Update
0021853FPCRTLpublic2013-02-13 20:17
ReporterBenjamin Rosseaux Assigned ToYuriy Sydorov  
PrioritynormalSeveritytweakReproducibilityN/A
Status resolvedResolutionfixed 
PlatformARM Linux / Android 
Product Version2.7.1 
Target Version2.7.1Fixed in Version3.0.0 
Summary0021853: IFDEF-conditional Android patch for the arm//linux RTL
DescriptionHere are my next android-oriented RTL patches for FPC, these will be only active, if the arm/linux RTL will be rebuilded with -dandroid as crosscompiling opts, for to be still compatible with normal non-android arm linux targets

At least the cthreads, errno and timezone patch parts are the most important things of it, otherwise the result binary cann't run often under a stock android environment, because of some missing or renamed system lib functions under android.

The patch is applied against SVN revision r21024.


Additional InformationAs a small hint: The one last SwapEndian ARM patch doesn't work with the android toolchain, so I've included a small change for it in this patch, so simply so keep this part, if you don't adopt this SwapEndian part.
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files

Relationships

related to 0020726 resolvedThomas Schatzl Basic support for Android 
related to 0021525 closedThomas Schatzl [patch]Threads don't work on Android 

Activities

2012-04-24 20:56

 

androidrtl.patch (21,714 bytes)   
Index: rtl/arm/arm.inc
===================================================================
--- rtl/arm/arm.inc	(revision 21024)
+++ rtl/arm/arm.inc	(working copy)
@@ -895,7 +895,7 @@
 function SwapEndian(const AValue: LongInt): LongInt;assembler;nostackframe;
 asm
         // We're starting with r0 = 4321
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov r2, r0, lsr #24             // r2 = 0004
         and r1, r0, #16711680           // r1 = 0300
         orr r2, r2, r0, lsl #24         // r2 = 1004
@@ -910,7 +910,7 @@
 function SwapEndian(const AValue: DWord): DWord;assembler;nostackframe;
 asm
         // We're starting with r0 = 4321
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov r2, r0, lsr #24             // r2 = 0004
         and r1, r0, #16711680           // r1 = 0300
         orr r2, r2, r0, lsl #24         // r2 = 1004
@@ -925,7 +925,7 @@
 function SwapEndian(const AValue: Int64): Int64; assembler; nostackframe;
 asm
         // We're starting with r0 = 4321 r1 = 8765
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov ip, r1
 
         mov r2, r0, lsr #24             // r2 = 0004
@@ -952,7 +952,7 @@
 function SwapEndian(const AValue: QWord): QWord; assembler; nostackframe;
 asm
         // We're starting with r0 = 4321 r1 = 8765
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov ip, r1
 
         mov r2, r0, lsr #24             // r2 = 0004
Index: rtl/inc/system.inc
===================================================================
--- rtl/inc/system.inc	(revision 21024)
+++ rtl/inc/system.inc	(working copy)
@@ -251,6 +251,20 @@
   {$Error Can't determine processor type !}
 {$endif}
 
+{$ifdef android}
+const ANDROID_LOG_UNKNOWN=0;
+      ANDROID_LOG_DEFAULT=1;
+      ANDROID_LOG_VERBOSE=2;
+      ANDROID_LOG_DEBUG=3;
+      ANDROID_LOG_INFO=4;
+      ANDROID_LOG_WARN=5;
+      ANDROID_LOG_ERROR=6;
+      ANDROID_LOG_FATAL=7;
+      ANDROID_LOG_SILENT=8;
+       
+function __android_log_write(prio:longint;tag,text:pchar):longint; cdecl; external 'liblog.so' name '__android_log_write';
+{$endif}
+
 procedure fillchar(var x;count : SizeInt;value : boolean);
 begin
   fillchar(x,count,byte(value));
@@ -885,6 +899,9 @@
 {$if defined(MSWINDOWS) or defined(OS2)}
   i : longint;
 {$endif}
+{$ifdef android}
+   s:shortstring;
+{$endif}   
 Begin
 {$ifdef SYSTEMDEBUG}
   writeln('InternalExit');
@@ -908,13 +925,24 @@
   pstdout:=@stdout;
   If erroraddr<>nil Then
    Begin
+{$ifdef android}
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar('** ****** **** ****** **** ****** **** ****** **'));
+   str(ErrorCode,s);   
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar(ansistring('Runtime error '+s+' at $'+hexstr(erroraddr))));
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar(ansistring(BackTraceStrFunc(Erroraddr))));
+   dump_stack(pstdout^,ErrorBase);
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar('** ****** **** ****** **** ****** **** ****** **'));
+{$else}
      Writeln(pstdout^,'Runtime error ',Errorcode,' at $',hexstr(erroraddr));
      { to get a nice symify }
      Writeln(pstdout^,BackTraceStrFunc(Erroraddr));
      dump_stack(pstdout^,ErrorBase);
      Writeln(pstdout^,'');
+{$endif}
    End;
+{$ifndef android}
   SysFlushStdIO;
+{$endif}
 {$endif EMBEDDED}
 {$endif FPC_HAS_FEATURE_CONSOLEIO}
 
@@ -1066,7 +1094,11 @@
        caller_frame := get_caller_frame(bp);
        if (caller_addr=nil) then
          break;
+{$ifdef android}         
+       __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(BackTraceStrFunc(caller_addr))));
+{$else}       
        Writeln(f,BackTraceStrFunc(caller_addr));
+{$endif}       
        if (caller_frame=nil) then
          break;
        Inc(i);
@@ -1092,11 +1124,19 @@
 begin
   if RaiseList=nil then
     exit;
+{$ifdef android}         
+   __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(BackTraceStrFunc(RaiseList^.Addr))));
+{$else}       
   WriteLn(f,BackTraceStrFunc(RaiseList^.Addr));
+{$endif}       
   FrameCount:=RaiseList^.Framecount;
   Frames:=RaiseList^.Frames;
   for FrameNumber := 0 to FrameCount-1 do
+{$ifdef android}         
+    __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(BackTraceStrFunc((Frames[FrameNumber])))));
+{$else}       
     WriteLn(f,BackTraceStrFunc(Frames[FrameNumber]));
+{$endif}       
 end;
 {$endif FPC_HAS_FEATURE_EXCEPTIONS}
 
@@ -1273,14 +1313,25 @@
 
 
 Procedure SysAssert(Const Msg,FName:Shortstring;LineNo:Longint;ErrorAddr:Pointer);
+{$ifdef android}
+var s:shortstring;
+{$endif}         
 begin
 {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
+{$ifdef android}         
+  str(LineNo,s);
   If msg='' then
+   __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring('Assertion failed ('+FName+', line '+s+')')))
+  else
+   __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(msg+' ('+FName+', line '+s+')')));
+{$else}       
+  If msg='' then
     write(stderr,'Assertion failed')
   else
     write(stderr,msg);
   Writeln(stderr,' (',FName,', line ',LineNo,').');
   Writeln(stderr,'');
+{$endif}       
   Halt(227);
 {$endif FPC_HAS_FEATURE_CONSOLEIO}
 end;
Index: rtl/linux/pthread.inc
===================================================================
--- rtl/linux/pthread.inc	(revision 21024)
+++ rtl/linux/pthread.inc	(working copy)
@@ -126,8 +126,10 @@
     function pthread_attr_getschedparam(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;external;
     function pthread_attr_setschedpolicy(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;external;
     function pthread_attr_getschedpolicy(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;external;
+{$ifndef android} 
     function pthread_attr_setinheritsched(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;external;
     function pthread_attr_getinheritsched(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;external;
+{$endif}
     function pthread_attr_setstacksize(p: ppthread_attr_t;s:size_t):cint;cdecl;external;
     function pthread_attr_getstacksize(p: ppthread_attr_t;s:psize_t):cint;cdecl;external;
     function pthread_attr_setscope(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;external;
@@ -141,32 +143,40 @@
     function pthread_mutex_unlock(__mutex:ppthread_mutex_t):longint;cdecl;external;
     function pthread_mutexattr_init(__attr:ppthread_mutexattr_t):longint;cdecl;external;
     function pthread_mutexattr_destroy(__attr:ppthread_mutexattr_t):longint;cdecl;external;
+{$ifndef android} 
     function pthread_mutexattr_setkind_np(__attr:ppthread_mutexattr_t; __kind:longint):longint;cdecl;external;
     function pthread_mutexattr_getkind_np(__attr:ppthread_mutexattr_t; __kind:plongint):longint;cdecl;external;
+{$endif}
     function pthread_cond_init(__cond:ppthread_cond_t; __cond_attr:ppthread_condattr_t):longint;cdecl;external;
     function pthread_cond_destroy(__cond:ppthread_cond_t):longint;cdecl;external;
     function pthread_cond_signal(__cond:ppthread_cond_t):longint;cdecl;external;
     function pthread_cond_broadcast(__cond:ppthread_cond_t):longint;cdecl;external;
     function pthread_cond_wait(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t):longint;cdecl;external;
     function pthread_cond_timedwait(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;external;
+{$ifndef android} 
     function pthread_condattr_init(__attr:ppthread_condattr_t):longint;cdecl;external;
     function pthread_condattr_destroy(__attr:ppthread_condattr_t):longint;cdecl;external;
+{$endif}
     function pthread_key_create(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;external;
     function pthread_key_delete(__key:pthread_key_t):longint;cdecl;external;
     function pthread_setspecific(__key:pthread_key_t; __pointer:pointer):longint;cdecl;external;
     function pthread_getspecific(__key:pthread_key_t):pointer;cdecl;external;
 {    function pthread_once(__once_control:ppthread_once_t; __init_routine:tprocedure ):longint;cdecl;external;}
+{$ifndef android} 
     function pthread_setcancelstate(__state:longint; __oldstate:plongint):longint;cdecl;external;
     function pthread_setcanceltype(__type:longint; __oldtype:plongint):longint;cdecl;external;
     function pthread_cancel(__thread:pthread_t):longint;cdecl;external;
     procedure pthread_testcancel;cdecl;external;
+{$endif}
 {    procedure _pthread_cleanup_push(__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_routine; __arg:pointer);cdecl;external; }
 {    procedure _pthread_cleanup_push_defer(__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_defer_routine; __arg:pointer);cdecl;external;}
 {    function pthread_sigmask(__how:longint; __newmask:plibc_sigset; __oldmask:plibc_sigset):longint;cdecl;external;}
     function pthread_kill(__thread:pthread_t; __signo:longint):longint;cdecl;external;
 {    function sigwait(__set:plibc_sigset; __sig:plongint):longint;cdecl;external;}
+{$ifndef android} 
     function pthread_atfork(__prepare:tprocedure ; __parent:tprocedure ; __child:tprocedure ):longint;cdecl;external;
     procedure pthread_kill_other_threads_np;cdecl;external;
+{$endif}
     function pthread_sigmask(how: cint; nset: plibc_sigset; oset: plibc_sigset): cint; cdecl; external;
 
     function sem_init (__sem:Psem_t; __pshared:longint; __value:dword):longint;cdecl;external;
@@ -197,8 +207,10 @@
     pthread_attr_getschedparam : Function(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;
     pthread_attr_setschedpolicy : Function(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;
     pthread_attr_getschedpolicy : Function(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;
+{$ifndef android} 
     pthread_attr_setinheritsched : Function(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;
     pthread_attr_getinheritsched : Function(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;
+{$endif}
     pthread_attr_setscope : Function(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;
     pthread_attr_getscope : Function(__attr:ppthread_attr_t; __scope:plongint):longint;cdecl;
     pthread_setschedparam : Function(__target_thread:pthread_t; __policy:longint; __param:psched_param):longint;cdecl;
@@ -211,32 +223,40 @@
     pthread_mutex_unlock : Function(__mutex:ppthread_mutex_t):longint;cdecl;
     pthread_mutexattr_init : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
     pthread_mutexattr_destroy : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
+{$ifndef android} 
     pthread_mutexattr_setkind_np : Function(__attr:ppthread_mutexattr_t; __kind:longint):longint;cdecl;
     pthread_mutexattr_getkind_np : Function(__attr:ppthread_mutexattr_t; __kind:plongint):longint;cdecl;
+{$endif}
     pthread_cond_init : Function(__cond:ppthread_cond_t; __cond_attr:ppthread_condattr_t):longint;cdecl;
     pthread_cond_destroy : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_signal : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_broadcast : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_wait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t):longint;cdecl;
     pthread_cond_timedwait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;
+{$ifndef android} 
     pthread_condattr_init : Function(__attr:ppthread_condattr_t):longint;cdecl;
     pthread_condattr_destroy : Function(__attr:ppthread_condattr_t):longint;cdecl;
+{$endif}
     pthread_key_create : Function(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;
     pthread_key_delete : Function(__key:pthread_key_t):longint;cdecl;
     pthread_setspecific : Function(__key:pthread_key_t; __pointer:pointer):longint;cdecl;
     pthread_getspecific : Function(__key:pthread_key_t):pointer;cdecl;
 {    pthread_once : Function(__once_control:ppthread_once_t; __init_routine:tprocedure ):longint;cdecl;}
+{$ifndef android} 
     pthread_setcancelstate : Function(__state:longint; __oldstate:plongint):longint;cdecl;
     pthread_setcanceltype : Function(__type:longint; __oldtype:plongint):longint;cdecl;
     pthread_cancel : Function(__thread:pthread_t):longint;cdecl;
     pthread_testcancel : Procedure ;cdecl;
+{$endif}
 {    _pthread_cleanup_push : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_routine; __arg:pointer);cdecl;}
 {    _pthread_cleanup_push_defer : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_defer_routine; __arg:pointer);cdecl;}
 {    pthread_sigmask : Function(__how:longint; __newmask:plibc_sigset; __oldmask:plibc_sigset):longint;cdecl;}
     pthread_kill : Function(__thread:pthread_t; __signo:longint):longint;cdecl;
 {    sigwait : Function(__set:plibc_sigset; __sig:plongint):longint;cdecl;}
+{$ifndef android} 
     pthread_atfork : Function(__prepare:tprocedure ; __parent:tprocedure ; __child:tprocedure ):longint;cdecl;
     pthread_kill_other_threads_np : procedure;cdecl;
+{$endif}
     pthread_sigmask: Function(how: cint; nset: plibc_sigset; oset: plibc_sigset): cint;cdecl;
 
     sem_init     :   function (__sem:Psem_t; __pshared:longint; __value:dword):longint;cdecl;
@@ -258,7 +278,7 @@
 Function LoadPthreads : Boolean;
 
 begin
-  PThreadDLL:=DlOpen('libpthread.so.0',RTLD_LAZY);
+  PThreadDLL:=DlOpen({$ifdef android}'libc.so'{$else}'libpthread.so.0'{$endif},RTLD_LAZY);
   Result:=PThreadDLL<>Nil;
   If Not Result then
     exit;
@@ -276,8 +296,10 @@
   Pointer(pthread_attr_getschedparam) := dlsym(PthreadDLL,'pthread_attr_getschedparam');
   Pointer(pthread_attr_setschedpolicy) := dlsym(PthreadDLL,'pthread_attr_setschedpolicy');
   Pointer(pthread_attr_getschedpolicy) := dlsym(PthreadDLL,'pthread_attr_getschedpolicy');
+{$ifndef android} 
   Pointer(pthread_attr_setinheritsched) := dlsym(PthreadDLL,'pthread_attr_setinheritsched');
   Pointer(pthread_attr_getinheritsched) := dlsym(PthreadDLL,'pthread_attr_getinheritsched');
+{$endif}
   Pointer(pthread_attr_setscope) := dlsym(PthreadDLL,'pthread_attr_setscope');
   Pointer(pthread_attr_getscope) := dlsym(PthreadDLL,'pthread_attr_getscope');
   Pointer(pthread_attr_setstacksize) := dlsym(PthreadDLL,'pthread_attr_setstacksize');
@@ -290,31 +312,39 @@
   Pointer(pthread_mutex_unlock) := dlsym(PthreadDLL,'pthread_mutex_unlock');
   Pointer(pthread_mutexattr_init) := dlsym(PthreadDLL,'pthread_mutexattr_init');
   Pointer(pthread_mutexattr_destroy) := dlsym(PthreadDLL,'pthread_mutexattr_destroy');
+{$ifndef android} 
   Pointer(pthread_mutexattr_setkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_setkind_np');
   Pointer(pthread_mutexattr_getkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_getkind_np');
+{$endif}
   Pointer(pthread_cond_init) := dlsym(PthreadDLL,'pthread_cond_init');
   Pointer(pthread_cond_destroy) := dlsym(PthreadDLL,'pthread_cond_destroy');
   Pointer(pthread_cond_signal) := dlsym(PthreadDLL,'pthread_cond_signal');
   Pointer(pthread_cond_broadcast) := dlsym(PthreadDLL,'pthread_cond_broadcast');
   Pointer(pthread_cond_wait) := dlsym(PthreadDLL,'pthread_cond_wait');
   Pointer(pthread_cond_timedwait) := dlsym(PthreadDLL,'pthread_cond_timedwait');
+{$ifndef android} 
   Pointer(pthread_condattr_init) := dlsym(PthreadDLL,'pthread_condattr_init');
   Pointer(pthread_condattr_destroy) := dlsym(PthreadDLL,'pthread_condattr_destroy');
+{$endif}
   Pointer(pthread_key_create) := dlsym(PthreadDLL,'pthread_key_create');
   Pointer(pthread_key_delete) := dlsym(PthreadDLL,'pthread_key_delete');
   Pointer(pthread_setspecific) := dlsym(PthreadDLL,'pthread_setspecific');
   Pointer(pthread_getspecific) := dlsym(PthreadDLL,'pthread_getspecific');
 {  Pointer(pthread_once) := dlsym(PthreadDLL,'pthread_once');}
+{$ifndef android} 
   Pointer(pthread_setcancelstate) := dlsym(PthreadDLL,'pthread_setcancelstate');
   Pointer(pthread_setcanceltype) := dlsym(PthreadDLL,'pthread_setcanceltype');
   Pointer(pthread_cancel) := dlsym(PthreadDLL,'pthread_cancel');
   Pointer(pthread_testcancel) := dlsym(PthreadDLL,'pthread_testcancel');
+{$endif}
 {  Pointer(_pthread_cleanup_push) := dlsym(PthreadDLL,'_pthread_cleanup_push');}
 {  Pointer(_pthread_cleanup_push_defer) := dlsym(PthreadDLL,'_pthread_cleanup_push_defer');}
 {  Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');}
   Pointer(pthread_kill)  := dlsym(PthreadDLL,'pthread_kill');
+{$ifndef android} 
   Pointer(pthread_atfork):= dlsym(PthreadDLL,'pthread_atfork');
   Pointer(pthread_kill_other_threads_np) := dlsym(PthreadDLL,'pthread_kill_other_threads_np');
+{$endif}
   Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');
   Pointer(sem_init     ) := dlsym(PthreadDLL,'sem_init');
   Pointer(sem_destroy  ) := dlsym(PthreadDLL,'sem_destroy');
Index: rtl/unix/cthreads.pp
===================================================================
--- rtl/unix/cthreads.pp	(revision 21024)
+++ rtl/unix/cthreads.pp	(working copy)
@@ -21,9 +21,13 @@
     b) still enabling dynamically checking whether or not certain functions
        are available (could also be implemented via weak linking)
 }
+{$ifdef android} 
+{$undef dynpthreads}
+{$else}
 {$linklib pthread}
 {$define dynpthreads} // Useless on BSD, since they are in libc
 {$endif}
+{$endif}
 
 
 { sem_init is best, since it does not consume any file descriptors.    }
@@ -54,9 +58,11 @@
 {$ifndef dynpthreads}   // If you have problems compiling this on FreeBSD 5.x
  {$linklib c}           // try adding -Xf
  {$if not defined(Darwin) and not defined(iphonesim)}
-   {$ifndef haiku}
+   {$ifndef android} 
+    {$ifndef haiku}
      {$linklib pthread}
-   {$endif haiku}
+    {$endif haiku}
+   {$endif android}
  {$endif darwin}
 {$endif}
 
@@ -332,13 +338,13 @@
       writeln('Starting new thread');
 {$endif DEBUG_MT}
       pthread_attr_init(@thread_attr);
-      {$ifndef HAIKU}
+      {$if not defined(HAIKU) and not defined(ANDROID)}
       {$ifdef solaris}
       pthread_attr_setinheritsched(@thread_attr, PTHREAD_INHERIT_SCHED);
       {$else not solaris}
       pthread_attr_setinheritsched(@thread_attr, PTHREAD_EXPLICIT_SCHED);
       {$endif not solaris}
-      {$endif}
+      {$ifend}
 
       // will fail under linux -- apparently unimplemented
       pthread_attr_setscope(@thread_attr, PTHREAD_SCOPE_PROCESS);
@@ -409,7 +415,14 @@
   function  CKillThread (threadHandle : TThreadID) : dword;
     begin
       pthread_detach(pthread_t(threadHandle));
+   {$ifdef android}
+
+      pthread_kill(pthread_t(threadHandle),SIGKILL);
+      
+   {$else}
+
       CKillThread := pthread_cancel(pthread_t(threadHandle));
+   {$endif} 
     end;
 
   function CCloseThread (threadHandle : TThreadID) : dword;
Index: rtl/unix/dl.pp
===================================================================
--- rtl/unix/dl.pp	(revision 21024)
+++ rtl/unix/dl.pp	(working copy)
@@ -33,7 +33,11 @@
 
 {$if defined(linux) and defined(cpuarm)}
 { arm-linux seems to require this }
-{$linklib c}
+  {$ifdef android} 
+    {$linklib dl}
+  {$else}
+    {$linklib c}
+  {$endif}
 {$endif}
 
 {$ifdef aix}
Index: rtl/unix/initc.pp
===================================================================
--- rtl/unix/initc.pp	(revision 21024)
+++ rtl/unix/initc.pp	(working copy)
@@ -52,7 +52,7 @@
 
 
 {$ifdef Linux}
-function geterrnolocation: pcint; cdecl;external clib name '__errno_location';
+function geterrnolocation: pcint; cdecl;external clib name   {$ifdef android}'__errno'{$else}'__errno_location'{$endif};
 {$endif}
 
 {$ifdef FreeBSD} // tested on x86
Index: rtl/unix/timezone.inc
===================================================================
--- rtl/unix/timezone.inc	(revision 21024)
+++ rtl/unix/timezone.inc	(working copy)
@@ -193,13 +193,20 @@
    fn:='localtime';
   if fn[1]<>'/' then
    begin
+{$ifdef android}   
+     fn:='/system/usr/share/zoneinfo/'+fn;
+{$else} 
      tzdir:=fpgetenv('TZDIR');
      if tzdir='' then
       tzdir:='/usr/share/zoneinfo';
      if tzdir[length(tzdir)]<>'/' then
       tzdir:=tzdir+'/';
      fn:=tzdir+fn;
+{$endif} 
    end;
+{$ifdef android}
+  exit;
+{$endif}   
   f:=fpopen(fn,Open_RdOnly);
   if f<0 then
    exit;
@@ -268,6 +275,9 @@
   TimeZoneFile = '/etc/localtime';                      // POSIX
   AltTimeZoneFile = '/usr/lib/zoneinfo/localtime';      // Other
   iOSTimeZoneFile = '/var/db/timezone/localtime';      // iOS
+{$ifdef android}
+  AndroidTimeZoneFile = '/system/usr/share/zoneinfo';      // Android
+{$ENDIF}
 {$ifdef BSD}
   BSDTimeZonefile = '/usr/share/zoneinfo';      // BSD usually is POSIX
                                                 // compliant though
@@ -304,6 +314,10 @@
 //       If fpstat(BSDTimeZoneFile,{$ifdef oldlinuxstat}baseunix.stat(info){$else}info{$endif})>=0 then
 // GetTimeZoneFile:=BSDTimeZoneFile
 {$ENDIF}
+{$ifdef android}
+  else If fpstat(AndroidTimeZoneFile,info)>=0 then
+      GetTimeZoneFile:=AndroidTimeZoneFile
+{$endif}
 {$if (defined(darwin) and defined(arm)) or defined(iphonesim)}
   else If fpstat(iOSTimeZoneFile,info)>=0 then
       GetTimeZoneFile:=iOSTimeZoneFile
androidrtl.patch (21,714 bytes)   

Andru

2012-04-24 21:15

reporter   ~0058951

As was discussed here:
http://bugs.freepascal.org/view.php?id=21525

pthread_kill with SIGKILL is wrong and will be never accepted to FPC, even with correct solution using SIGUSR1.

Benjamin Rosseaux

2012-04-24 21:34

reporter   ~0058952

@andru this part of this patch can be skip then simply, so where is the problem with it?

Benjamin Rosseaux

2012-04-24 21:35

reporter   ~0058953

Simply with a empty stub code, that do then nothing at android or that raise a "unimplemented"-exception etc.

2012-04-24 21:46

 

androidrtl2.patch (21,791 bytes)   
Index: rtl/arm/arm.inc
===================================================================
--- rtl/arm/arm.inc	(revision 21025)
+++ rtl/arm/arm.inc	(working copy)
@@ -895,7 +895,7 @@
 function SwapEndian(const AValue: LongInt): LongInt;assembler;nostackframe;
 asm
         // We're starting with r0 = 4321
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov r2, r0, lsr #24             // r2 = 0004
         and r1, r0, #16711680           // r1 = 0300
         orr r2, r2, r0, lsl #24         // r2 = 1004
@@ -910,7 +910,7 @@
 function SwapEndian(const AValue: DWord): DWord;assembler;nostackframe;
 asm
         // We're starting with r0 = 4321
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov r2, r0, lsr #24             // r2 = 0004
         and r1, r0, #16711680           // r1 = 0300
         orr r2, r2, r0, lsl #24         // r2 = 1004
@@ -925,7 +925,7 @@
 function SwapEndian(const AValue: Int64): Int64; assembler; nostackframe;
 asm
         // We're starting with r0 = 4321 r1 = 8765
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov ip, r1
 
         mov r2, r0, lsr #24             // r2 = 0004
@@ -952,7 +952,7 @@
 function SwapEndian(const AValue: QWord): QWord; assembler; nostackframe;
 asm
         // We're starting with r0 = 4321 r1 = 8765
-{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5)}
+{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}
         mov ip, r1
 
         mov r2, r0, lsr #24             // r2 = 0004
Index: rtl/inc/system.inc
===================================================================
--- rtl/inc/system.inc	(revision 21025)
+++ rtl/inc/system.inc	(working copy)
@@ -251,6 +251,20 @@
   {$Error Can't determine processor type !}
 {$endif}
 
+{$ifdef android}
+const ANDROID_LOG_UNKNOWN=0;
+      ANDROID_LOG_DEFAULT=1;
+      ANDROID_LOG_VERBOSE=2;
+      ANDROID_LOG_DEBUG=3;
+      ANDROID_LOG_INFO=4;
+      ANDROID_LOG_WARN=5;
+      ANDROID_LOG_ERROR=6;
+      ANDROID_LOG_FATAL=7;
+      ANDROID_LOG_SILENT=8;
+       
+function __android_log_write(prio:longint;tag,text:pchar):longint; cdecl; external 'liblog.so' name '__android_log_write';
+{$endif}
+
 procedure fillchar(var x;count : SizeInt;value : boolean);
 begin
   fillchar(x,count,byte(value));
@@ -885,6 +899,9 @@
 {$if defined(MSWINDOWS) or defined(OS2)}
   i : longint;
 {$endif}
+{$ifdef android}
+   s:shortstring;
+{$endif}   
 Begin
 {$ifdef SYSTEMDEBUG}
   writeln('InternalExit');
@@ -908,13 +925,24 @@
   pstdout:=@stdout;
   If erroraddr<>nil Then
    Begin
+{$ifdef android}
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar('** ****** **** ****** **** ****** **** ****** **'));
+   str(ErrorCode,s);   
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar(ansistring('Runtime error '+s+' at $'+hexstr(erroraddr))));
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar(ansistring(BackTraceStrFunc(Erroraddr))));
+   dump_stack(pstdout^,ErrorBase);
+   __android_log_write(ANDROID_LOG_FATAL,pansichar('FPCRTL'),pansichar('** ****** **** ****** **** ****** **** ****** **'));
+{$else}
      Writeln(pstdout^,'Runtime error ',Errorcode,' at $',hexstr(erroraddr));
      { to get a nice symify }
      Writeln(pstdout^,BackTraceStrFunc(Erroraddr));
      dump_stack(pstdout^,ErrorBase);
      Writeln(pstdout^,'');
+{$endif}
    End;
+{$ifndef android}
   SysFlushStdIO;
+{$endif}
 {$endif EMBEDDED}
 {$endif FPC_HAS_FEATURE_CONSOLEIO}
 
@@ -1066,7 +1094,11 @@
        caller_frame := get_caller_frame(bp);
        if (caller_addr=nil) then
          break;
+{$ifdef android}         
+       __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(BackTraceStrFunc(caller_addr))));
+{$else}       
        Writeln(f,BackTraceStrFunc(caller_addr));
+{$endif}       
        if (caller_frame=nil) then
          break;
        Inc(i);
@@ -1092,11 +1124,19 @@
 begin
   if RaiseList=nil then
     exit;
+{$ifdef android}         
+   __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(BackTraceStrFunc(RaiseList^.Addr))));
+{$else}       
   WriteLn(f,BackTraceStrFunc(RaiseList^.Addr));
+{$endif}       
   FrameCount:=RaiseList^.Framecount;
   Frames:=RaiseList^.Frames;
   for FrameNumber := 0 to FrameCount-1 do
+{$ifdef android}         
+    __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(BackTraceStrFunc((Frames[FrameNumber])))));
+{$else}       
     WriteLn(f,BackTraceStrFunc(Frames[FrameNumber]));
+{$endif}       
 end;
 {$endif FPC_HAS_FEATURE_EXCEPTIONS}
 
@@ -1273,14 +1313,25 @@
 
 
 Procedure SysAssert(Const Msg,FName:Shortstring;LineNo:Longint;ErrorAddr:Pointer);
+{$ifdef android}
+var s:shortstring;
+{$endif}         
 begin
 {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
+{$ifdef android}         
+  str(LineNo,s);
   If msg='' then
+   __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring('Assertion failed ('+FName+', line '+s+')')))
+  else
+   __android_log_write(ANDROID_LOG_FATAL,'FPCRTL',pansichar(ansistring(msg+' ('+FName+', line '+s+')')));
+{$else}       
+  If msg='' then
     write(stderr,'Assertion failed')
   else
     write(stderr,msg);
   Writeln(stderr,' (',FName,', line ',LineNo,').');
   Writeln(stderr,'');
+{$endif}       
   Halt(227);
 {$endif FPC_HAS_FEATURE_CONSOLEIO}
 end;
Index: rtl/linux/pthread.inc
===================================================================
--- rtl/linux/pthread.inc	(revision 21025)
+++ rtl/linux/pthread.inc	(working copy)
@@ -126,8 +126,10 @@
     function pthread_attr_getschedparam(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;external;
     function pthread_attr_setschedpolicy(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;external;
     function pthread_attr_getschedpolicy(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;external;
+{$ifndef android} 
     function pthread_attr_setinheritsched(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;external;
     function pthread_attr_getinheritsched(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;external;
+{$endif}
     function pthread_attr_setstacksize(p: ppthread_attr_t;s:size_t):cint;cdecl;external;
     function pthread_attr_getstacksize(p: ppthread_attr_t;s:psize_t):cint;cdecl;external;
     function pthread_attr_setscope(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;external;
@@ -141,32 +143,40 @@
     function pthread_mutex_unlock(__mutex:ppthread_mutex_t):longint;cdecl;external;
     function pthread_mutexattr_init(__attr:ppthread_mutexattr_t):longint;cdecl;external;
     function pthread_mutexattr_destroy(__attr:ppthread_mutexattr_t):longint;cdecl;external;
+{$ifndef android} 
     function pthread_mutexattr_setkind_np(__attr:ppthread_mutexattr_t; __kind:longint):longint;cdecl;external;
     function pthread_mutexattr_getkind_np(__attr:ppthread_mutexattr_t; __kind:plongint):longint;cdecl;external;
+{$endif}
     function pthread_cond_init(__cond:ppthread_cond_t; __cond_attr:ppthread_condattr_t):longint;cdecl;external;
     function pthread_cond_destroy(__cond:ppthread_cond_t):longint;cdecl;external;
     function pthread_cond_signal(__cond:ppthread_cond_t):longint;cdecl;external;
     function pthread_cond_broadcast(__cond:ppthread_cond_t):longint;cdecl;external;
     function pthread_cond_wait(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t):longint;cdecl;external;
     function pthread_cond_timedwait(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;external;
+{$ifndef android} 
     function pthread_condattr_init(__attr:ppthread_condattr_t):longint;cdecl;external;
     function pthread_condattr_destroy(__attr:ppthread_condattr_t):longint;cdecl;external;
+{$endif}
     function pthread_key_create(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;external;
     function pthread_key_delete(__key:pthread_key_t):longint;cdecl;external;
     function pthread_setspecific(__key:pthread_key_t; __pointer:pointer):longint;cdecl;external;
     function pthread_getspecific(__key:pthread_key_t):pointer;cdecl;external;
 {    function pthread_once(__once_control:ppthread_once_t; __init_routine:tprocedure ):longint;cdecl;external;}
+{$ifndef android} 
     function pthread_setcancelstate(__state:longint; __oldstate:plongint):longint;cdecl;external;
     function pthread_setcanceltype(__type:longint; __oldtype:plongint):longint;cdecl;external;
     function pthread_cancel(__thread:pthread_t):longint;cdecl;external;
     procedure pthread_testcancel;cdecl;external;
+{$endif}
 {    procedure _pthread_cleanup_push(__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_routine; __arg:pointer);cdecl;external; }
 {    procedure _pthread_cleanup_push_defer(__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_defer_routine; __arg:pointer);cdecl;external;}
 {    function pthread_sigmask(__how:longint; __newmask:plibc_sigset; __oldmask:plibc_sigset):longint;cdecl;external;}
     function pthread_kill(__thread:pthread_t; __signo:longint):longint;cdecl;external;
 {    function sigwait(__set:plibc_sigset; __sig:plongint):longint;cdecl;external;}
+{$ifndef android} 
     function pthread_atfork(__prepare:tprocedure ; __parent:tprocedure ; __child:tprocedure ):longint;cdecl;external;
     procedure pthread_kill_other_threads_np;cdecl;external;
+{$endif}
     function pthread_sigmask(how: cint; nset: plibc_sigset; oset: plibc_sigset): cint; cdecl; external;
 
     function sem_init (__sem:Psem_t; __pshared:longint; __value:dword):longint;cdecl;external;
@@ -197,8 +207,10 @@
     pthread_attr_getschedparam : Function(__attr:ppthread_attr_t; __param:psched_param):longint;cdecl;
     pthread_attr_setschedpolicy : Function(__attr:ppthread_attr_t; __policy:longint):longint;cdecl;
     pthread_attr_getschedpolicy : Function(__attr:ppthread_attr_t; __policy:plongint):longint;cdecl;
+{$ifndef android} 
     pthread_attr_setinheritsched : Function(__attr:ppthread_attr_t; __inherit:longint):longint;cdecl;
     pthread_attr_getinheritsched : Function(__attr:ppthread_attr_t; __inherit:plongint):longint;cdecl;
+{$endif}
     pthread_attr_setscope : Function(__attr:ppthread_attr_t; __scope:longint):longint;cdecl;
     pthread_attr_getscope : Function(__attr:ppthread_attr_t; __scope:plongint):longint;cdecl;
     pthread_setschedparam : Function(__target_thread:pthread_t; __policy:longint; __param:psched_param):longint;cdecl;
@@ -211,32 +223,40 @@
     pthread_mutex_unlock : Function(__mutex:ppthread_mutex_t):longint;cdecl;
     pthread_mutexattr_init : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
     pthread_mutexattr_destroy : Function(__attr:ppthread_mutexattr_t):longint;cdecl;
+{$ifndef android} 
     pthread_mutexattr_setkind_np : Function(__attr:ppthread_mutexattr_t; __kind:longint):longint;cdecl;
     pthread_mutexattr_getkind_np : Function(__attr:ppthread_mutexattr_t; __kind:plongint):longint;cdecl;
+{$endif}
     pthread_cond_init : Function(__cond:ppthread_cond_t; __cond_attr:ppthread_condattr_t):longint;cdecl;
     pthread_cond_destroy : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_signal : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_broadcast : Function(__cond:ppthread_cond_t):longint;cdecl;
     pthread_cond_wait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t):longint;cdecl;
     pthread_cond_timedwait : Function(__cond:ppthread_cond_t; __mutex:ppthread_mutex_t; __abstime:ptimespec):longint;cdecl;
+{$ifndef android} 
     pthread_condattr_init : Function(__attr:ppthread_condattr_t):longint;cdecl;
     pthread_condattr_destroy : Function(__attr:ppthread_condattr_t):longint;cdecl;
+{$endif}
     pthread_key_create : Function(__key:ppthread_key_t; __destr_function:__destr_function_t):longint;cdecl;
     pthread_key_delete : Function(__key:pthread_key_t):longint;cdecl;
     pthread_setspecific : Function(__key:pthread_key_t; __pointer:pointer):longint;cdecl;
     pthread_getspecific : Function(__key:pthread_key_t):pointer;cdecl;
 {    pthread_once : Function(__once_control:ppthread_once_t; __init_routine:tprocedure ):longint;cdecl;}
+{$ifndef android} 
     pthread_setcancelstate : Function(__state:longint; __oldstate:plongint):longint;cdecl;
     pthread_setcanceltype : Function(__type:longint; __oldtype:plongint):longint;cdecl;
     pthread_cancel : Function(__thread:pthread_t):longint;cdecl;
     pthread_testcancel : Procedure ;cdecl;
+{$endif}
 {    _pthread_cleanup_push : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_routine; __arg:pointer);cdecl;}
 {    _pthread_cleanup_push_defer : procedure (__buffer:p_pthread_cleanup_buffer;__routine:t_pthread_cleanup_push_defer_routine; __arg:pointer);cdecl;}
 {    pthread_sigmask : Function(__how:longint; __newmask:plibc_sigset; __oldmask:plibc_sigset):longint;cdecl;}
     pthread_kill : Function(__thread:pthread_t; __signo:longint):longint;cdecl;
 {    sigwait : Function(__set:plibc_sigset; __sig:plongint):longint;cdecl;}
+{$ifndef android} 
     pthread_atfork : Function(__prepare:tprocedure ; __parent:tprocedure ; __child:tprocedure ):longint;cdecl;
     pthread_kill_other_threads_np : procedure;cdecl;
+{$endif}
     pthread_sigmask: Function(how: cint; nset: plibc_sigset; oset: plibc_sigset): cint;cdecl;
 
     sem_init     :   function (__sem:Psem_t; __pshared:longint; __value:dword):longint;cdecl;
@@ -258,7 +278,7 @@
 Function LoadPthreads : Boolean;
 
 begin
-  PThreadDLL:=DlOpen('libpthread.so.0',RTLD_LAZY);
+  PThreadDLL:=DlOpen({$ifdef android}'libc.so'{$else}'libpthread.so.0'{$endif},RTLD_LAZY);
   Result:=PThreadDLL<>Nil;
   If Not Result then
     exit;
@@ -276,8 +296,10 @@
   Pointer(pthread_attr_getschedparam) := dlsym(PthreadDLL,'pthread_attr_getschedparam');
   Pointer(pthread_attr_setschedpolicy) := dlsym(PthreadDLL,'pthread_attr_setschedpolicy');
   Pointer(pthread_attr_getschedpolicy) := dlsym(PthreadDLL,'pthread_attr_getschedpolicy');
+{$ifndef android} 
   Pointer(pthread_attr_setinheritsched) := dlsym(PthreadDLL,'pthread_attr_setinheritsched');
   Pointer(pthread_attr_getinheritsched) := dlsym(PthreadDLL,'pthread_attr_getinheritsched');
+{$endif}
   Pointer(pthread_attr_setscope) := dlsym(PthreadDLL,'pthread_attr_setscope');
   Pointer(pthread_attr_getscope) := dlsym(PthreadDLL,'pthread_attr_getscope');
   Pointer(pthread_attr_setstacksize) := dlsym(PthreadDLL,'pthread_attr_setstacksize');
@@ -290,31 +312,39 @@
   Pointer(pthread_mutex_unlock) := dlsym(PthreadDLL,'pthread_mutex_unlock');
   Pointer(pthread_mutexattr_init) := dlsym(PthreadDLL,'pthread_mutexattr_init');
   Pointer(pthread_mutexattr_destroy) := dlsym(PthreadDLL,'pthread_mutexattr_destroy');
+{$ifndef android} 
   Pointer(pthread_mutexattr_setkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_setkind_np');
   Pointer(pthread_mutexattr_getkind_np) := dlsym(PthreadDLL,'pthread_mutexattr_getkind_np');
+{$endif}
   Pointer(pthread_cond_init) := dlsym(PthreadDLL,'pthread_cond_init');
   Pointer(pthread_cond_destroy) := dlsym(PthreadDLL,'pthread_cond_destroy');
   Pointer(pthread_cond_signal) := dlsym(PthreadDLL,'pthread_cond_signal');
   Pointer(pthread_cond_broadcast) := dlsym(PthreadDLL,'pthread_cond_broadcast');
   Pointer(pthread_cond_wait) := dlsym(PthreadDLL,'pthread_cond_wait');
   Pointer(pthread_cond_timedwait) := dlsym(PthreadDLL,'pthread_cond_timedwait');
+{$ifndef android} 
   Pointer(pthread_condattr_init) := dlsym(PthreadDLL,'pthread_condattr_init');
   Pointer(pthread_condattr_destroy) := dlsym(PthreadDLL,'pthread_condattr_destroy');
+{$endif}
   Pointer(pthread_key_create) := dlsym(PthreadDLL,'pthread_key_create');
   Pointer(pthread_key_delete) := dlsym(PthreadDLL,'pthread_key_delete');
   Pointer(pthread_setspecific) := dlsym(PthreadDLL,'pthread_setspecific');
   Pointer(pthread_getspecific) := dlsym(PthreadDLL,'pthread_getspecific');
 {  Pointer(pthread_once) := dlsym(PthreadDLL,'pthread_once');}
+{$ifndef android} 
   Pointer(pthread_setcancelstate) := dlsym(PthreadDLL,'pthread_setcancelstate');
   Pointer(pthread_setcanceltype) := dlsym(PthreadDLL,'pthread_setcanceltype');
   Pointer(pthread_cancel) := dlsym(PthreadDLL,'pthread_cancel');
   Pointer(pthread_testcancel) := dlsym(PthreadDLL,'pthread_testcancel');
+{$endif}
 {  Pointer(_pthread_cleanup_push) := dlsym(PthreadDLL,'_pthread_cleanup_push');}
 {  Pointer(_pthread_cleanup_push_defer) := dlsym(PthreadDLL,'_pthread_cleanup_push_defer');}
 {  Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');}
   Pointer(pthread_kill)  := dlsym(PthreadDLL,'pthread_kill');
+{$ifndef android} 
   Pointer(pthread_atfork):= dlsym(PthreadDLL,'pthread_atfork');
   Pointer(pthread_kill_other_threads_np) := dlsym(PthreadDLL,'pthread_kill_other_threads_np');
+{$endif}
   Pointer(pthread_sigmask) := dlsym(PthreadDLL,'pthread_sigmask');
   Pointer(sem_init     ) := dlsym(PthreadDLL,'sem_init');
   Pointer(sem_destroy  ) := dlsym(PthreadDLL,'sem_destroy');
Index: rtl/unix/cthreads.pp
===================================================================
--- rtl/unix/cthreads.pp	(revision 21025)
+++ rtl/unix/cthreads.pp	(working copy)
@@ -21,9 +21,13 @@
     b) still enabling dynamically checking whether or not certain functions
        are available (could also be implemented via weak linking)
 }
+{$ifdef android} 
+{$undef dynpthreads}
+{$else}
 {$linklib pthread}
 {$define dynpthreads} // Useless on BSD, since they are in libc
 {$endif}
+{$endif}
 
 
 { sem_init is best, since it does not consume any file descriptors.    }
@@ -54,9 +58,11 @@
 {$ifndef dynpthreads}   // If you have problems compiling this on FreeBSD 5.x
  {$linklib c}           // try adding -Xf
  {$if not defined(Darwin) and not defined(iphonesim)}
-   {$ifndef haiku}
+   {$ifndef android} 
+    {$ifndef haiku}
      {$linklib pthread}
-   {$endif haiku}
+    {$endif haiku}
+   {$endif android}
  {$endif darwin}
 {$endif}
 
@@ -332,13 +338,13 @@
       writeln('Starting new thread');
 {$endif DEBUG_MT}
       pthread_attr_init(@thread_attr);
-      {$ifndef HAIKU}
+      {$if not defined(HAIKU) and not defined(ANDROID)}
       {$ifdef solaris}
       pthread_attr_setinheritsched(@thread_attr, PTHREAD_INHERIT_SCHED);
       {$else not solaris}
       pthread_attr_setinheritsched(@thread_attr, PTHREAD_EXPLICIT_SCHED);
       {$endif not solaris}
-      {$endif}
+      {$ifend}
 
       // will fail under linux -- apparently unimplemented
       pthread_attr_setscope(@thread_attr, PTHREAD_SCOPE_PROCESS);
@@ -408,8 +414,18 @@
 
   function  CKillThread (threadHandle : TThreadID) : dword;
     begin
+   {$ifdef android}
+
+//    pthread_detach(pthread_t(threadHandle));
+//    pthread_kill(pthread_t(threadHandle),SIGKILL);
+
+      CKillThread := 0;
+      
+   {$else}
+
       pthread_detach(pthread_t(threadHandle));
       CKillThread := pthread_cancel(pthread_t(threadHandle));
+   {$endif} 
     end;
 
   function CCloseThread (threadHandle : TThreadID) : dword;
Index: rtl/unix/dl.pp
===================================================================
--- rtl/unix/dl.pp	(revision 21025)
+++ rtl/unix/dl.pp	(working copy)
@@ -33,7 +33,11 @@
 
 {$if defined(linux) and defined(cpuarm)}
 { arm-linux seems to require this }
-{$linklib c}
+  {$ifdef android} 
+    {$linklib dl}
+  {$else}
+    {$linklib c}
+  {$endif}
 {$endif}
 
 {$ifdef aix}
Index: rtl/unix/initc.pp
===================================================================
--- rtl/unix/initc.pp	(revision 21025)
+++ rtl/unix/initc.pp	(working copy)
@@ -52,7 +52,7 @@
 
 
 {$ifdef Linux}
-function geterrnolocation: pcint; cdecl;external clib name '__errno_location';
+function geterrnolocation: pcint; cdecl;external clib name   {$ifdef android}'__errno'{$else}'__errno_location'{$endif};
 {$endif}
 
 {$ifdef FreeBSD} // tested on x86
Index: rtl/unix/timezone.inc
===================================================================
--- rtl/unix/timezone.inc	(revision 21025)
+++ rtl/unix/timezone.inc	(working copy)
@@ -193,13 +193,20 @@
    fn:='localtime';
   if fn[1]<>'/' then
    begin
+{$ifdef android}   
+     fn:='/system/usr/share/zoneinfo/'+fn;
+{$else} 
      tzdir:=fpgetenv('TZDIR');
      if tzdir='' then
       tzdir:='/usr/share/zoneinfo';
      if tzdir[length(tzdir)]<>'/' then
       tzdir:=tzdir+'/';
      fn:=tzdir+fn;
+{$endif} 
    end;
+{$ifdef android}
+  exit;
+{$endif}   
   f:=fpopen(fn,Open_RdOnly);
   if f<0 then
    exit;
@@ -268,6 +275,9 @@
   TimeZoneFile = '/etc/localtime';                      // POSIX
   AltTimeZoneFile = '/usr/lib/zoneinfo/localtime';      // Other
   iOSTimeZoneFile = '/var/db/timezone/localtime';      // iOS
+{$ifdef android}
+  AndroidTimeZoneFile = '/system/usr/share/zoneinfo';      // Android
+{$ENDIF}
 {$ifdef BSD}
   BSDTimeZonefile = '/usr/share/zoneinfo';      // BSD usually is POSIX
                                                 // compliant though
@@ -304,6 +314,10 @@
 //       If fpstat(BSDTimeZoneFile,{$ifdef oldlinuxstat}baseunix.stat(info){$else}info{$endif})>=0 then
 // GetTimeZoneFile:=BSDTimeZoneFile
 {$ENDIF}
+{$ifdef android}
+  else If fpstat(AndroidTimeZoneFile,info)>=0 then
+      GetTimeZoneFile:=AndroidTimeZoneFile
+{$endif}
 {$if (defined(darwin) and defined(arm)) or defined(iphonesim)}
   else If fpstat(iOSTimeZoneFile,info)>=0 then
       GetTimeZoneFile:=iOSTimeZoneFile
androidrtl2.patch (21,791 bytes)   

Benjamin Rosseaux

2012-04-24 21:47

reporter   ~0058955

So androidrtl2.patch contains now a IFDEF-android-block empty stub for CKillThread

Andru

2012-04-24 22:12

reporter   ~0058959

Last edited: 2012-04-24 22:14

>> @andru this part of this patch can be skip then simply, so where is the problem with it?

Nowhere, but FPC DevTeam(or only one developer?) have some principals as I understood, so FreePascal for Android will never arrive. Or something will happen and Android developers will add a lot of missing stuff into their Bionic in some Android 5/6/7/infinity version... :)

Benjamin Rosseaux

2012-04-24 22:36

reporter   ~0058960

i've good contact with FPK (Florian) on the IRC, so don't worry :) So he said to me that I should submit my patch here and no any word of rejecting, since my patch introduces only small changes and that also with conditonal IFDEF blocks, for to be still compatible with normal non-android arm linux targets (so a android target "opt-in" conditional define).

Andru

2012-04-24 22:49

reporter   ~0058961

Last edited: 2012-04-24 22:49

I had the same IFDEF blocks, but as you can see - I got only very polite version of "your patch is a cr*p" with explanation where I'm wrong(funny that I wrote about the pointed problem) and without any help in solving CKillThread problem :) But I'm glad about "i've good contact with FPK (Florian) on the IRC, so don't worry", so maybe something will move from dead point )

Thomas Schatzl

2012-04-26 15:22

developer   ~0059019

There is now an official branch (http://svn.freepascal.org/svn/fpc/branches/targetandroid/) containing preliminary android support in the compiler

Some comments about the changes:

 - arm.inc: the changes for swapendian seem wrong, armv6 introduces the used "rev" instruction. There is another issue at hand. You should compile the compiler/rtl with armv5 support only if needed.
 - system.inc: while the change is good, it might be better to change stdout to use __android_log_write itself, just like for gui-only apps in windows
 - cthreads.pp: I guess the best and most obvious would be some sort of Unimplemented() call that exits the program with a stack trace instead of silently ignoring the failure. I think something like that already exists. Jonas?
 - dl.pp, initc.pp: not needed in the new branch if I am correct

@andru: the solution with "SIGUSR1" is no solution. While searching for that issue on the 'net I saw that others already tried that, but found out that SIGUSR1 is already used by dalvik (http://blogs.mentor.com/hollisblanchard/blog/tag/android/) - so this is no solution, or using any other hardcoded signal.
I recommend not using pthread_cancel due to the known issues with resource management, race conditions etc, so I am all for exiting with a fatal error if possible.

Thomas Schatzl

2012-04-26 17:54

developer   ~0059024

Another option for the KillThread issue is to just return STATUS_NOT_SUPPORTED on Android as some other implementations do in such a case.

Benjamin Rosseaux

2012-04-26 17:58

reporter   ~0059025

@Thomas Schatzl, ARMv5 as target is no solution for me, since I'm using VFP for realtime sound synthesis, 3D graphic calculations and other stuff, that doesn't support by <=ARMv5. And the detour over fixed-point is also no more a solution for today on modern smartphone/tablet CPUs.

Und I've removed the cpuarmv6 from "{$if defined(cpuarmv3) or defined(cpuarmv4) or defined(cpuarmv5) or defined(cpuarmv6)}" because AS from my ARM toolchain outputs a unknown instruction error at the REV instruction (where CortexA8 is set as AS/LD target with "-mcpu=cortex-a8", and at FPC is set to ARMv6+VFPv3). Maybe I should change the toolchain with a self-built ARM toolchain.

Thomas Schatzl

2012-04-26 21:02

developer   ~0059027

I was not suggesting to not use the extensions, just that that particular change is incorrect.

As a temporary solution you can also simply create wrapper scripts to as and ld with some prefix (that add the needed params), and use -XP to compile instead of making new binutils.

Thomas Schatzl

2012-04-26 21:15

developer   ~0059028

I have a question about the timezone.inc changes:

On android, ReadTimeZoneFile() exits after setting the filename, but does not read anything. What's the point of that particular fix?

Benjamin Rosseaux

2012-04-27 01:33

reporter   ~0059032

"As a temporary solution you can also simply create wrapper scripts to as and ld with some prefix (that add the needed params), and use -XP to compile instead of making new binutils."

This is that, what I'm already doing.

And to the timezone stuff, android has a own binary-based file format for it, and on a try to read it with the current code a exception is raising, because the code tries to allocate an too large memory block then, so the whole app crashes then.

And fpGetEnv doesn't even work on android, the current fpGetEnv implementation crashes on android also, not on all android versions but only on some android versions (mostly android <=3.2, while on androud >=4.0 runs it in the most cases without any problems).

I'm owning five android devices. On 3 from 5 devices at me fpGetEnv crashes the whole app through a AccessViolation Exception on checking on a #0 end-char of the env string.

Because of this bug-found (in android itself I believe) I've disabled the whole ReadTimeZoneFile stuff including the fpGetEnv call.

Thomas Schatzl

2012-04-27 11:05

developer   ~0059041

Ok, so this just means that ReadTimeZoneFile() must be completely changed for android, not just hack-fixed. Thanks for the info.

As for fpgetenv, this is a completely different issue: it's not a bug in Android, it's a feature of Linux and your use of the arm/linux compiler.

Android does not pass argc/argv/envp to shared libraries, but default arm/linux shared library startup files assume so, basically loading random values into the env string which crashes the program when accessed.

This has been "fixed" in that earlier mentioned branch by (temporarily) setting the environment string to nil at least for now. I am working on fixing that somehow, but I assume that it will likely require linking to bionic/libc by default in the end (not that you mentioned that you do not want that).

Marco van de Voort

2012-10-06 14:42

manager   ~0062937

If Android is a separate target, maybe we can enable FPC_USE_LIBC for it?

Yuriy Sydorov

2013-02-13 20:17

manager   ~0065677

The Android target is now in trunk. Many bugs has been fixed. Please test and close if OK.

Issue History

Date Modified Username Field Change
2012-04-24 20:56 Benjamin Rosseaux New Issue
2012-04-24 20:56 Benjamin Rosseaux File Added: androidrtl.patch
2012-04-24 21:15 Andru Note Added: 0058951
2012-04-24 21:34 Benjamin Rosseaux Note Added: 0058952
2012-04-24 21:35 Benjamin Rosseaux Note Added: 0058953
2012-04-24 21:46 Benjamin Rosseaux File Added: androidrtl2.patch
2012-04-24 21:47 Benjamin Rosseaux Note Added: 0058955
2012-04-24 22:12 Andru Note Added: 0058959
2012-04-24 22:14 Andru Note Edited: 0058959
2012-04-24 22:22 Marco van de Voort Relationship added related to 0020726
2012-04-24 22:36 Benjamin Rosseaux Note Added: 0058960
2012-04-24 22:49 Andru Note Added: 0058961
2012-04-24 22:49 Andru Note Edited: 0058961
2012-04-26 15:22 Thomas Schatzl Note Added: 0059019
2012-04-26 15:25 Thomas Schatzl Relationship added related to 0021525
2012-04-26 17:54 Thomas Schatzl Note Added: 0059024
2012-04-26 17:58 Benjamin Rosseaux Note Added: 0059025
2012-04-26 21:02 Thomas Schatzl Note Added: 0059027
2012-04-26 21:15 Thomas Schatzl Note Added: 0059028
2012-04-27 01:33 Benjamin Rosseaux Note Added: 0059032
2012-04-27 11:05 Thomas Schatzl Note Added: 0059041
2012-07-07 22:56 Thomas Schatzl Status new => assigned
2012-07-07 22:56 Thomas Schatzl Assigned To => Thomas Schatzl
2012-10-06 14:42 Marco van de Voort Note Added: 0062937
2013-02-13 20:17 Yuriy Sydorov Assigned To Thomas Schatzl => Yuriy Sydorov
2013-02-13 20:17 Yuriy Sydorov Note Added: 0065677
2013-02-13 20:17 Yuriy Sydorov Status assigned => resolved
2013-02-13 20:17 Yuriy Sydorov Fixed in Version => 2.7.1
2013-02-13 20:17 Yuriy Sydorov Resolution open => fixed
2013-02-13 20:17 Yuriy Sydorov Target Version => 2.7.1