View Issue Details

IDProjectCategoryView StatusLast Update
0038864FPCRTLpublic2021-05-08 20:38
ReporterMichael Ring Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
PlatformembeddedOSembedded 
Product Version3.3.1 
Summary0038864: Including sysutil in embedded project crashes app
DescriptionProblem is that TEncoding uses Criticalsection:

class constructor TEncoding.Create;
var
  E: TStandardEncoding;
begin
  for E := Low(FStandardEncodings) to High(FStandardEncodings) do
    FStandardEncodings[E] := nil;
{$ifdef FPC_HAS_FEATURE_THREADING}
  InitCriticalSection(FLock);
{$endif}
end;

which needs an instanciated ThreadManager, but that one is initialized after TEncoding so we get a null pointer exception:

#0 RP2040_$$__HARDFAULT_HANDLER at arm/cortexm0p_start.inc:22
0000001 <signal handler called> at :0
0000002 ?? at :0
0000003 INITCRITICALSECTION({__M_RESERVED = 0, __M_COUNT = 0, __M_OWNER = 0x0, __M_KIND = 0, __M_LOCK = {__STATUS = 0, __SPINLOCK = 0}}) at ../inc/thread.inc:230
0000004 create at ../objpas/sysutils/sysencoding.inc:214
0000005 SYSUTILS_$$_init$ at sysutils.pp:291
0000006 FPC_INIT_FUNC_TABLE at :0
0000007 main at i2c_ds3231.lpr:28
0000008 STARTUP at arm/cortexm0p_start.inc:90


Here's the piece of code that is causing the exception, what I do not understand is where the dependency comes from, it looks injected by the compiler:

../objpas/sysutils/sysutils.inc:667
1000C230 0ab0 add sp, 0000040 ; 0x28
1000C232 30bd pop {r4, r5, pc}
1000C234 b406 lsls r4, r6, 0000026
1000C236 0020 movs r0, #0
1000C238 00b5 push {lr}
1000C23A 88b0 sub sp, 0000032
1000C23C fff7e2f9 bl 0x1000b604 <SYSUTILS$_$TENCODING_$__$$_$create>
1000C240 fff780ff bl 0x1000c144 <SYSUTILS_$$_INITEXCEPTIONS>
1000C244 08b0 add sp, 0000032
1000C246 00bd pop {pc}
Steps To ReproduceBuild a simple elf file for arm-embedded (see attachment)

and then run:

 arm-none-eabi-objdump project1.elf -d >somefile.txt

then open the file and search for

SYSUTILS_$$_init$

0800bf94 <SYSUTILS_$$_init$>:
 800bf94: b500 push {lr}
 800bf96: b088 sub sp, 0000032
 800bf98: f7ff f9e2 bl 800b360 <SYSUTILS$_$TENCODING_$__$$_$create>
 800bf9c: f7ff ff80 bl 800bea0 <SYSUTILS_$$_INITEXCEPTIONS>
 800bfa0: b008 add sp, 0000032
 800bfa2: bd00 pop {pc}

there you will find the wrong initialization order
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files

Activities

Michael Ring

2021-05-07 12:09

reporter  

project1.lpi (1,489 bytes)   
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
  <ProjectOptions>
    <Version Value="12"/>
    <General>
      <Flags>
        <MainUnitHasCreateFormStatements Value="False"/>
        <MainUnitHasTitleStatement Value="False"/>
        <MainUnitHasScaledStatement Value="False"/>
        <LRSInOutputDirectory Value="False"/>
        <CompatibilityMode Value="True"/>
      </Flags>
      <SessionStorage Value="InProjectDir"/>
      <Title Value="project1"/>
    </General>
    <BuildModes Count="1">
      <Item1 Name="Default" Default="True"/>
    </BuildModes>
    <PublishOptions>
      <Version Value="2"/>
    </PublishOptions>
    <RunParams>
      <FormatVersion Value="2"/>
      <Modes Count="1">
        <Mode0 Name="default"/>
      </Modes>
    </RunParams>
    <Units Count="1">
      <Unit0>
        <Filename Value="project1.lpr"/>
        <IsPartOfProject Value="True"/>
      </Unit0>
    </Units>
  </ProjectOptions>
  <CompilerOptions>
    <Version Value="11"/>
    <Parsing>
      <SyntaxOptions>
        <UseAnsiStrings Value="False"/>
      </SyntaxOptions>
    </Parsing>
    <CodeGeneration>
      <TargetProcessor Value="ARMV6M"/>
      <TargetCPU Value="arm"/>
      <TargetOS Value="embedded"/>
    </CodeGeneration>
    <Linking>
      <Debugging>
        <UseLineInfoUnit Value="False"/>
      </Debugging>
    </Linking>
    <Other>
      <CustomOptions Value="-WpSTM32F091CB
-godwarfsets
-godwarfcpp
-Xu
-al"/>
    </Other>
  </CompilerOptions>
</CONFIG>
project1.lpi (1,489 bytes)   
project1.lpr (46 bytes)   
program project1;
uses
  sysutils;
begin
end.
project1.lpr (46 bytes)   

Christo Crause

2021-05-08 10:41

reporter   ~0130797

The default thread manager should be initialized in system, but for embedded that call is commented, and points to an empty procedure anyway. In rtl/freertos/systhrd.inc a default thread manager stub is defined, perhaps that can be copied across to work around the critical section problem.

Alternatively, if you have a proper thread manager as a separate unit, include that unit before sysutils so that the thread manager is already configured before sysutils gets initialized.

Michael Ring

2021-05-08 15:16

reporter   ~0130799

From what I can tell all the needed groundwork is already done, in inc/thread.inc I see:

Procedure SetNoThreadManager;
begin
  SetThreadManager(NoThreadManager);
end;

which initializes Threadmanager to some routines that at least for criticalsection does not seem to do harm.

So I think we have the following options:

Workarround: undefine -SfTHREADING for embeddeded targets in system.cfg (this is what I currently do)

Waste some memory for embedded targets and call SetNoThreadManager to create a threadmanager instance, haven't tried that yet but see that in wii/systhrd.inc exactly this step was done and I see that special care for embedded was taken in SetNoThreadManager

But I do not know which of those two ways (or a third one??) is the correct solution.

Christo Crause

2021-05-08 16:25

reporter   ~0130800

Yes you are correct, I should have looked at thread.inc first. It seems as if freertos/systhrd.inc is a stripped down version of the NoThreadManager in thread.inc.

I assume -SfTHREADING is defined for targets that can handle threads, even if FPC doesn't provide an implementation yet. If -SfTHREADING is disabled then installing a user thread manager will have no real effect because the RTL will not call thread aware functionality. Thus if a target is thread capable (-SfTHREADING is defined), system initialization should call SetNoThreadManager (either via InitSystemThreads or directly in the init code of system) to fix your current issue.

At least that is my view, let us see what one of the real devs say.

Michael Ring

2021-05-08 20:38

reporter   ~0130802

Based on your hints I have created this patch, will try if this makes thigs better or worse for embedded....

diff --git a/rtl/embedded/system.pp b/rtl/embedded/system.pp
index 1a06200b7c..f12464affc 100644
--- a/rtl/embedded/system.pp
+++ b/rtl/embedded/system.pp
@@ -35,7 +35,7 @@ Unit System;

 { $define USE_NOTHREADMANAGER}

-{$define DISABLE_NO_THREAD_MANAGER}
+{ $define DISABLE_NO_THREAD_MANAGER}
 { Do not use standard memory manager }
 {$define HAS_MEMORYMANAGER}
 {$define FPC_NO_DEFAULT_HEAP}
@@ -300,7 +300,7 @@ begin

 {$ifdef FPC_HAS_FEATURE_THREADING}
   { threading }
- //InitSystemThreads; // Empty call for embedded anyway
+ InitSystemThreads;
 {$endif FPC_HAS_FEATURE_THREADING}

 {$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
diff --git a/rtl/embedded/systhrd.inc b/rtl/embedded/systhrd.inc
index b2dacab49a..2d07cda567 100644
--- a/rtl/embedded/systhrd.inc
+++ b/rtl/embedded/systhrd.inc
@@ -16,6 +16,10 @@

 Procedure InitSystemThreads;
 begin
+ { This should be changed to a real value during
+ thread driver initialization if appropriate. }
+ ThreadID := 1;
+ SetNoThreadManager;
 end;

Issue History

Date Modified Username Field Change
2021-05-07 12:09 Michael Ring New Issue
2021-05-07 12:09 Michael Ring File Added: project1.lpi
2021-05-07 12:09 Michael Ring File Added: project1.lpr
2021-05-08 10:41 Christo Crause Note Added: 0130797
2021-05-08 15:16 Michael Ring Note Added: 0130799
2021-05-08 16:25 Christo Crause Note Added: 0130800
2021-05-08 20:38 Michael Ring Note Added: 0130802