From 20ee3c3f6c16c3550427082b15f6bb389fbc2db3 Mon Sep 17 00:00:00 2001
From: Ben Avison <bavison@gitlab.riscosopen.org>
Date: Tue, 2 Dec 2003 16:51:33 +0000
Subject: [PATCH] Changes for Customer W; also suitable for building on an
 Iyonix.

Detail:
  * No longer uses aasm to build h.swis.
  * (Only) compatible with new C compilers: assumes const static data is
    placed in separate read-only areas, and suitable command-line switch
    is used to ensure that library static data is never placed in a zero-
    init area.
  * Stack extension code now thread-safe.
  * Heap thread-safety code (in clib) now uses SWP instruction test results
    from stack extension code (in kernel) - as a side effect, the exported
    symbol _swp_available now exists, if you need to use it elsewhere.
  * Slightly closer to having top-bit-set heap addresses working.
Admin:
  Tested in a Tungsten build, and with Customer W's test suite.

Version 5.48. Tagged as 'RISC_OSLib-5_48'
---
 Makefile        | 16 +++++++---
 VersionASM      | 14 ++++----
 VersionNum      | 22 ++++++-------
 c/alloc         | 29 +++--------------
 clib/s/cl_spare |  2 +-
 h/alloc         |  1 +
 kernel/s/k_body | 85 ++++++++++++++++++++++++++++++++++++++++++++++---
 kernel/s/k_data |  4 ++-
 s/makehswis     |  2 ++
 9 files changed, 122 insertions(+), 53 deletions(-)

diff --git a/Makefile b/Makefile
index 618ba61..22f1044 100644
--- a/Makefile
+++ b/Makefile
@@ -53,7 +53,7 @@ LIBDIR  = <Lib$Dir>
 #
 # Generic options:
 #
-AS      = aasm
+AS      = objasm
 CC      = cc
 CMHG    = cmhg
 CP      = copy
@@ -71,8 +71,9 @@ XTENT   = perl build:xtentries >
 
 DIFF    = gnu.diff -df >null:
 
-AFLAGS  = -depend !Depend -Stamp -quit
-CFLAGS  = -c -depend !Depend ${INCLUDES} -DDDE -fK
+AFLAGS  = -depend !Depend
+# The zz switch stops library static data being placed in a zero-init area
+CFLAGS  = -c -depend !Depend ${INCLUDES} -DDDE -fK -zz10000000
 CPFLAGS = ~cfr~v
 WFLAGS  = ~c~r~v
 
@@ -632,8 +633,13 @@ lib.clib: ${CLIB_MOD_OBJS}
 	${MODSQZ} $@
 
 # Derived headers:
-derived.swis: s.makehswis h.swisheader s.swioptions
-	${AS} ${AFLAGS} -from s.makehswis -to $@
+derived.swis: o.swis
+	${LD} -bin -o $@ o.SWIs
+	stripnulls $@
+	settype $@ text
+
+o.swis: s.makehswis h.swisheader s.swioptions
+	${AS} ${AFLAGS} s.makehswis -o $@
 	settype $@ text
 
 s.swioptions:
diff --git a/VersionASM b/VersionASM
index 87252b7..c5a8945 100644
--- a/VersionASM
+++ b/VersionASM
@@ -1,6 +1,6 @@
 ;
 ; This file is automatically maintained by srccommit, do not edit manually.
-; Last processed by srccommit version: 1.68.
+; Last processed by srccommit version: 1.2.
 ;
                         GBLS    Module_MajorVersion
                         GBLA    Module_Version
@@ -11,13 +11,13 @@
                         GBLS    Module_HelpVersion
                         GBLS    Module_ComponentName
                         GBLS    Module_ComponentPath
-Module_MajorVersion     SETS    "5.47"
-Module_Version          SETA    547
+Module_MajorVersion     SETS    "5.48"
+Module_Version          SETA    548
 Module_MinorVersion     SETS    ""
-Module_Date             SETS    "03 Nov 2003"
-Module_ApplicationDate  SETS    "03-Nov-03"
+Module_Date             SETS    "02 Dec 2003"
+Module_ApplicationDate  SETS    "02-Dec-03"
 Module_ComponentName    SETS    "RISC_OSLib"
 Module_ComponentPath    SETS    "RiscOS/Sources/Lib/RISC_OSLib"
-Module_FullVersion      SETS    "5.47"
-Module_HelpVersion      SETS    "5.47 (03 Nov 2003)"
+Module_FullVersion      SETS    "5.48"
+Module_HelpVersion      SETS    "5.48 (02 Dec 2003)"
                         END
diff --git a/VersionNum b/VersionNum
index 96f7a40..83bd420 100644
--- a/VersionNum
+++ b/VersionNum
@@ -1,23 +1,23 @@
-/* (5.47)
+/* (5.48)
  *
  * This file is automatically maintained by srccommit, do not edit manually.
- * Last processed by srccommit version: 1.68.
+ * Last processed by srccommit version: 1.2.
  *
  */
-#define Module_MajorVersion_CMHG        5.47
+#define Module_MajorVersion_CMHG        5.48
 #define Module_MinorVersion_CMHG        
-#define Module_Date_CMHG                03 Nov 2003
+#define Module_Date_CMHG                02 Dec 2003
 
-#define Module_MajorVersion             "5.47"
-#define Module_Version                  547
+#define Module_MajorVersion             "5.48"
+#define Module_Version                  548
 #define Module_MinorVersion             ""
-#define Module_Date                     "03 Nov 2003"
+#define Module_Date                     "02 Dec 2003"
 
-#define Module_ApplicationDate          "03-Nov-03"
+#define Module_ApplicationDate          "02-Dec-03"
 
 #define Module_ComponentName            "RISC_OSLib"
 #define Module_ComponentPath            "RiscOS/Sources/Lib/RISC_OSLib"
 
-#define Module_FullVersion              "5.47"
-#define Module_HelpVersion              "5.47 (03 Nov 2003)"
-#define Module_LibraryVersionInfo       "5:47"
+#define Module_FullVersion              "5.48"
+#define Module_HelpVersion              "5.48 (02 Dec 2003)"
+#define Module_LibraryVersionInfo       "5:48"
diff --git a/c/alloc b/c/alloc
index 446a080..33ad2a5 100644
--- a/c/alloc
+++ b/c/alloc
@@ -248,37 +248,23 @@ static char sys_message[60];
 /* Mutex-y things */
 
 static int heapMutex;
-static jmp_buf *swpNotAvailable = NULL; /* boolean also used to pass jmp_buf to sig handler */
+extern int _swp_available;
 
+#ifndef __APCS_32
 static int arm2_swp(int newValue, int *location);
+#endif
 
 static inline int swp(int newValue, int *location)
 {
 #ifndef __APCS_32
-  if (swpNotAvailable) return arm2_swp(newValue, location);
+  if (!_swp_available) return arm2_swp(newValue, location);
 #endif
   int oldValue;
   __asm { SWP oldValue, newValue, [location] }
   return oldValue;
 }
 
-#ifdef __APCS_32
 #define INITMUTEX heapMutex = 1
-#else
-#define INITMUTEX \
-  do { \
-    heapMutex = 1; \
-    jmp_buf jb; \
-    swpNotAvailable = &jb; \
-    void (*old_sig_handler)(int) = signal(SIGILL, temp_sig_handler); \
-    if (setjmp(jb) == 0) { \
-      int temp; \
-      __asm { SWP temp, 1, [&heapMutex] } \
-      swpNotAvailable = NULL; \
-    } \
-    signal(SIGILL, old_sig_handler); \
-  } while (0)
-#endif
 
 #define ACQUIREMUTEX \
   do { \
@@ -1077,7 +1063,7 @@ extern void *malloc(size_t size)
 
   ENTRYTOALLOC(ptr);
   ptr = (void *)_primitive_alloc(BYTESTOWORDS(size));
-  if ((int)ptr < OK) {
+  if ((unsigned)ptr >= MINHEAPERROR) {
 #ifdef STATS
     ShowStats();
 #endif
@@ -1162,11 +1148,6 @@ extern void _init_user_alloc(void)
 }
 
 #ifndef __APCS_32
-static void temp_sig_handler(int sig)
-{
-  longjmp(*swpNotAvailable, 1);
-}
-
 static int arm2_swp(int newValue, int *location)
 {
   int irqs_off = _kernel_irqs_disabled();
diff --git a/clib/s/cl_spare b/clib/s/cl_spare
index e2c330d..21060a8 100644
--- a/clib/s/cl_spare
+++ b/clib/s/cl_spare
@@ -25,7 +25,7 @@
 
         EXPORT  |CLib_data_end|
 
-        %       112*4
+        %       124*4
 |CLib_data_end|
 
         END
diff --git a/h/alloc b/h/alloc
index f6625f7..13b4966 100644
--- a/h/alloc
+++ b/h/alloc
@@ -56,6 +56,7 @@ typedef struct BlockStruct {
 #define OK       0
 #define FAILED  -1
 #define CORRUPT -2
+#define MINHEAPERROR -2 /* ensure you update this if you add any new errors */
 
 #define SIZEMASK      0xfffffffc /* all except bottom two bits, when applied */
                                  /* to block.size yields no of address units */
diff --git a/kernel/s/k_body b/kernel/s/k_body
index e385931..f64e10c 100644
--- a/kernel/s/k_body
+++ b/kernel/s/k_body
@@ -408,6 +408,14 @@ uwb_size        #       0
         ; this chunk - they won't ever be used.  We must set mark (to be
         ; not IsAStackChunk) and SL_xxx_Offset. Also prev.
         STR     sp, [v6, #O_extendChunk]
+      [ {CONFIG}<>26
+        MOV     r0, #1
+        STR     r0, [v6, #O__swp_available]
+      |
+        BL      CheckIfSwpAvailable
+      ]
+        MOV     r0, #1
+        STR     r0, [v6, #O_extendChunkNotInUse]
         ADD     r0, sl, #SL_Lib_Offset
         LDMIA   r0, {r1, r2}
         ADD     r0, sp, #SC_SLOffset+SL_Lib_Offset
@@ -512,6 +520,41 @@ NoMainProgram
 FatalError Keep
         SWI     GenerateError
 
+ [ {CONFIG}=26
+; v6 = static base
+; sp -> extendChunk, which we will use as workspace
+; assumed entered in USR mode with SVC stack empty
+CheckIfSwpAvailable
+        STMIA   sp!, {r0-r12,r14}      ; error handler might corrupt anything
+        MOV     r0, #0                 ; start off assuming error will happen
+        STR     r0, [v6, #O__swp_available]
+
+        MOV     r0, #6
+        MOV     r1, #0
+        MOV     r2, #0
+        MOV     r3, #0
+        SWI     XOS_ChangeEnvironment           ; read existing error handler
+        STMIA   sp!, {r1-r3}
+        MOV     r0, #6
+        ADR     r1, %FT01
+        MOV     r2, sp
+        MOV     r3, sp
+        SWI     XOS_ChangeEnvironment           ; set temp error handler
+
+        SWP     r0, r0, [sp]                    ; try a SWP
+
+        MOV     r0, #1
+        STR     r0, [v6, #O__swp_available]     ; note we were successful
+        B       %FT02
+01
+        MOV     sp, r0                          ; put back sp after error
+02
+        MOV     r0, #6
+        LDMDB   sp!, {r1-r3}
+        SWI     XOS_ChangeEnvironment           ; restore error handler
+        LDMDB   sp!, {r0-r12,pc}
+ ]
+
 ;StrongARM - there is dynamic code here, but this is sorted in _kernel_init, after
 ;all calls to CopyHandler
 CopyHandler
@@ -2624,8 +2667,8 @@ alloc_return_block
 ; as only ip is free.
 ; We can save things on the stack a distance below fp which allows the
 ; largest possible list of saved work registers (r0-r3, r4-r9 inclusive,
-; plus fp, sp, lr, entry pc, = 14 regs in total) plus a minimal stack
-; frame for return from StkOvfExit (a further 4 words, giving 18 in total)
+; plus fp, sp, lr = 13 regs in total) plus a minimal stack
+; frame for return from StkOvfExit (a further 4 words, giving 17 in total)
 ; plus 4 extended floating point registers (a further 3*4 words)
         MOV     ip, sp
 |_kernel_stkovf_split|
@@ -2849,6 +2892,19 @@ StkOvfGetNewChunk Keep
         ; Now we swap to the special extension chunk (to give a reasonable
         ; stack size to malloc).
         LoadStaticBase v2, ip
+03      MOV     a1, #0
+        ADD     a2, v2, #O_extendChunkNotInUse
+      [ {CONFIG}=26
+        LDR     lr, [v2, #O__swp_available]
+        TEQ     lr, #0
+        SWPNE   a1, a1, [a2]
+        BLEQ    Arm2Swp
+      |
+        SWP     a1, a1, [a2]
+      ]
+        TEQ     a1, #0
+        BLEQ    Sleep                     ; preserves Z
+        BEQ     %BT03
         LDR     a2, [v2, #O_extendChunk]
         LDR     a3, [a2, #SC_size]
         ADD     a3, a2, a3                ; new sp
@@ -2863,14 +2919,17 @@ StkOvfGetNewChunk Keep
         LDR     ip, [v2, #O_allocProc]
         CMPS    ip, #0
         BEQ     %F01                    ; (restore stack chunk, then error)
-        LDR     v2, [v2, #O_freeProc]
-        STMFD   sp!, {a1, v2}           ; chunk size in bytes, dealloc proc
+        LDR     lr, [v2, #O_freeProc]
+        STMFD   sp!, {a1, lr}           ; chunk size in bytes, dealloc proc
         MOV     lr, pc
         MOV     pc, ip
+        MOV     lr, v2
         MOVS    v2, a1
         LDMFD   sp!, {v3, ip}           ; size in bytes, dealloc
 01
         LDMFD   sp, {sl, fp, sp}        ; back to old chunk
+        MOV     a1, #1
+        STR     a1, [lr, #O_extendChunkNotInUse]
         BEQ     StkOvfError
         STR     v3, [v2, #SC_size]
         STR     ip, [v2, #SC_deallocate]
@@ -2913,6 +2972,24 @@ StackOverflowFault Keep
 
         ErrorBlock StackOverflow, "Stack overflow", C45
 
+ [ {CONFIG}=26
+Arm2Swp ; like SWP a1,a1,[a2] but corrupts a3, lr and flags
+        SWI     IntOff
+        LDR     a3, [a2]
+        STR     a1, [a2]
+        SWI     IntOn
+        MOV     a1, a3
+        MOV     pc, lr
+ ]
+
+Sleep
+; a2 -> pollword
+; must exit with Z set
+        MOV     a1, #6
+        SWI     &20033 ; XOS_UpCall
+        CMP     a1, a1
+        MOV     pc, lr
+
  ;*-------------------------------------------------------------------*
  ;* Arithmetic                                                        *
  ;*-------------------------------------------------------------------*
diff --git a/kernel/s/k_data b/kernel/s/k_data
index fb0fb77..e2d59c8 100644
--- a/kernel/s/k_data
+++ b/kernel/s/k_data
@@ -104,6 +104,8 @@ initSlotSize            Variable
 
 lk_RestoreOSHandlers    Variable
 extendChunk             Variable
+extendChunkNotInUse     Variable
+_swp_available          ExportedVariable
 rootStackChunk          Variable
 
 ; Tmp space for expanding PC value in fatal error handler
@@ -117,6 +119,6 @@ reg_hex_buff            Variable        3
 
 disable_stack_extension ExportedVariable 1
 
-unused                  Variable        16
+unused                  Variable        14
 
         END
diff --git a/s/makehswis b/s/makehswis
index 55e4d97..9670b35 100644
--- a/s/makehswis
+++ b/s/makehswis
@@ -104,6 +104,8 @@ string2 SETS    "&":CC:(:STR:value)
 ;SoundWorkSpace * &01F04000
         GET     Hdr:PublicWS
 
+        AREA    |Text$Data|, DATA
+
 ; First output the file header
 	BIN	h.swisheader
 
-- 
GitLab