ain@s.cc.purdue.edu (Patrick White) (07/21/88)
Does anybody know what the dos and don'ts are to write reentrant code with Manx 3.4? (or 3.6 as I will be upgrading to that soon). For example, I know that static (global) variables are out, but are there any other things? (like string constants?) While we are on the subject, what about reentrant code in all the other languages for the Amiga.. like pascal, and assembly, and modula2, and Lattice C :-)? Thanks. -- Pat White ARPA/UUCP: s.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906
dillon@CORY.BERKELEY.EDU (Matt Dillon) (07/24/88)
> Does anybody know what the dos and don'ts are to write reentrant code with >Manx 3.4? (or 3.6 as I will be upgrading to that soon). > > For example, I know that static (global) variables are out, but are there >any other things? (like string constants?) > > While we are on the subject, what about reentrant code in all the other >languages for the Amiga.. like pascal, and assembly, and modula2, and >Lattice C :-)? > > Thanks. Mainly, you have to stay away from most link-library routines (C.LIB). As you said, globals, unless they are constants, are out. For example, SysBase and DOSBase are globals but never change, so they are ok. STDIO (in C.LIB) is DEFINATELY out. If you stick to run-time library calls and keep in mind your code might be running simultaniously in different contexes, you should be fine. AVOID RETURNING STRUCTURES. Many compilers, Aztec included (I'm pretty sure), use static memory to hold structural return values. I don't know of anybody who uses the [mis]feature, though. STATIC variables, unless used purposefully, are also out. NOTE: This means using the main() entry point is out, as it sets up stdio. I am not sure about using _main() ... it might work. If all else fails, you can compile your code +B, and assuming there are no other references to .begin, the code is entered at the first module. In this case you must remember that global variables will NOT be zero'd initially, and neither the DOS or EXEC libraries will be open. Did I miss anything? -Matt
jvkelley@watcgl.waterloo.edu (Jeff Kelley) (07/25/88)
In article <3415@s.cc.purdue.edu> ain@s.cc.purdue.edu (Patrick White) writes: > > For example, I know that static (global) variables are out, but are there >any other things? (like string constants?) > With Lattice C 4.01, it is possible to have up to 64k of global variables and reentrancy. Essentially, you use address register a4 as a free parameter pass between all your functions. You just have to be careful to initialize it correctly. Global variables are handy because the Lattice compiler will generate code to access amiga libraries (other than Exec) with references to the library base as a global variable. (e.g. using intuition.library involves an access to IntuitionBase). My technique allows string constants, but only with a bit of trickery to put them in the code section rather than the data section. > While we are on the subject, what about reentrant code in all the other >languages for the Amiga.. like pascal, and assembly, and modula2, and >Lattice C :-)? This method will only work for Lattice C 4.01. I use it to write ROMmable Exec devices in C (with a tiny piece of assembler glue common to all the devices I've written). Writing Exec libraries currently requires a little assembler for each library entry point to get parameters out of registers, but if the "#pragma libcall" feature of Lattice would support passing arguments to libraries on the stack, even this wouldn't be necessary. Anyway, I've deviated from the topic at hand. Here's a shar file which explains the technique and contains a demo 'Hello, world' program. -- Jeff Kelley Graphics Lab, Dept. of Computer Science, University of Waterloo uunet!watmath!watcgl!jvkelley tel: (519) 578-4514 "Remember, this is not a competition, only an exhibition. Please, no wagering." - David Letterman # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by watcgl!jvkelley on Sun Jul 24 14:42:26 EDT 1988 # Contents: README data.c datatocode.c hw.c makefile startup.asm strings.c echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' Here's a simple example showing how to create a Lattice C 4.01 load file with no data or bss sections. The global variable section, pointed to by register a4, is dynamically allocated. Note that this only works with the small data model and limits the combined size of globals to 64k. The technique involved requires that all global variable declarations be placed in one file, and referenced as 'extern's in other files where they are used. It is not possible to statically initialize these variables, although they may be assumed to be zero if you clear the memory dynamically allocated for them. The trick involves the use of what is either a bug or a feature of 'blink'. It seems that if you have only one bss section in one of the object files, and no data sections in any of them, then the bss section will not appear in the load file. References to the bss section will be resolved as if it existed, however, and this allows one to dynamically allocate it. Note that if even a single data section is present during linking, the linking will either fail or produce an unwanted resultant load file. I suggest linking first with the 'PRELINK' option to 'blink', and 'omd'ing this file to ensure that no data or bss sections are present. It is also important to realize that strings are placed in the data section. It is possible to put them in the code section by declaring them in a separate file, changing the data section of the object produced by that file to a code section, and referencing the strings as external functions. (Very gross.) I've written a data hunk to code hunk translator to assist with this operation. (source in datatocode.c) Many library routines (in lc.lib and amiga.lib, for example) have data sections and are thus off limits. Anyway, included herein is a 'hello, world' demo of the technique. -- Jeff Kelley Graphics Lab, Dept. of Computer Science, University of Waterloo uunet!watmath!watcgl!jvkelley tel: (519) 578-4514 "Remember, this is not a competition, only an exhibition. Please, no wagering." - David Letterman @//E*O*F README// chmod u=rw,g=r,o=r README echo x - data.c sed 's/^@//' > "data.c" <<'@//E*O*F data.c//' unsigned long DOSBase; @//E*O*F data.c// chmod u=rw,g=r,o=r data.c echo x - datatocode.c sed 's/^@//' > "datatocode.c" <<'@//E*O*F datatocode.c//' #include <stdio.h> #define HUNK_DATA 0x3EAL #define HUNK_CODE 0x3E9L #define HUNK_BSS 0x3EBL void main(argc, argv) int argc; char *argv[]; { FILE *pf; unsigned long i; char *name; if (argc < 2 || argc > 3) { puts("Usage: dc [-z] <file>"); exit(1); } if (argc == 3) { if (strcmp(argv[1],"-z")) { puts("Bad option"); exit(1); } name = argv[2]; } else name = argv[1]; if (!(pf = fopen(name, "r+"))) { puts("Can't open file"); exit(1); } while (fread((char *)&i, sizeof(i), 1, pf) == 1) { if (argc == 2) { if (i == HUNK_DATA) { fseek(pf,-sizeof(i),1); i = HUNK_CODE; fwrite((char *)&i,sizeof(i),1,pf); break; } } else { if (i == HUNK_BSS) { i = 0; fseek(pf,0,1); fwrite((char *)&i,sizeof(i),1,pf); break; } } } fclose(pf); } @//E*O*F datatocode.c// chmod u=rw,g=r,o=r datatocode.c echo x - hw.c sed 's/^@//' > "hw.c" <<'@//E*O*F hw.c//' #include <exec/types.h> #include <string.h> #include <proto/exec.h> #include <proto/dos.h> extern struct DosLibrary *DOSBase; extern char *HelloWorld(); extern char *DosName(); void myputs(s) char *s; { Write(Output(), s, strlen(s)); } void main() { DOSBase = (struct DosLibrary *)OpenLibrary((char *)DosName,0); myputs(HelloWorld); CloseLibrary((struct Library *)DOSBase); } @//E*O*F hw.c// chmod u=rw,g=r,o=r hw.c echo x - makefile sed 's/^@//' > "makefile" <<'@//E*O*F makefile//' LN = blink CC = lc CFLAGS = -v -d AS = asm all: datatocode hw datatocode: datatocode.o $(CC) $(CFLAGS) -L datatocode.c hw: hw.pre $(LN) from hw.pre to hw NODEBUG hw.pre: hw.o data.o strings.o startup.o $(LN) from startup.o hw.o data.o strings.o to hw.pre lib lib:lc.lib PRELINK SMALLCODE SMALLDATA hw.o: hw.c $(CC) $(CFLAGS) hw.c data.o: data.c $(CC) $(CFLAGS) data.c strings.o: strings.c $(CC) -v -b0 strings.c datatocode strings.o startup.o: startup.asm $(AS) startup.asm @//E*O*F makefile// chmod u=rw,g=r,o=r makefile echo x - startup.asm sed 's/^@//' > "startup.asm" <<'@//E*O*F startup.asm//' SECTION startup,CODE XREF _main ABSEXECBASE EQU 4 DATASIZE EQU 4 move.l ABSEXECBASE.w,a6 move.l #DATASIZE,d0 moveq.l #0,d1 jsr -$00c6(a6) AllocMem tst.l d0 beq nomem movea.l d0,a4 Set up base register jsr _main move.l ABSEXECBASE.w,a6 movea.l a4,a1 move.l #DATASIZE,d0 jsr -$00d2(a6) FreeMem nomem: rts END @//E*O*F startup.asm// chmod u=rw,g=r,o=r startup.asm echo x - strings.c sed 's/^@//' > "strings.c" <<'@//E*O*F strings.c//' char HelloWorld[] = "Hello, world.\n"; char DosName[] = "dos.library"; @//E*O*F strings.c// chmod u=rw,g=r,o=r strings.c exit 0