Bournegol (2014)
8 points by icefox
8 points by icefox
This provoked me to try to remind myself about the details of the Bourne shell memory allocator, because it has a reputation for causing horrible problems when porting the shell from the PDP11 to other computers.
But tbh, I’m not sure how it worked…
The intro to Bournegol is the macros that make C look vaguely like Algol 68 https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h
But there are also macros that make C look more like BCPL (which is amazing given how close C was to BCPL already).
And there are signs in the code that suggest to me that some of the macros predate the introduction of cast syntax (type)value into C, which happened some time between 6th edition unix and k&r, which was shortly before 7th edition unix.
The fun part of the allocator that caused the portability headaches was in https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/fault.c where the signal handler says
IF sig==MEMF
THEN IF setbrk(brkincr) == -1
THEN error(nospace);
FI
MEMF is an alias for SIGSEGV, so when that happens it just asks the kernel to extend its segment and returns from the signal handler.
Which implies that the allocator just walks off the end of its segment hoping for the best, and the segv handler tries to make the best happen.
So let’s take a look at the allocator in https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/blok.c
BLKPTR bloktop=BLK(end); /*top of arena (last blok)*/
…
bloktop=bloktop->word=BLK(Rcheat(bloktop)+reqd);
bloktop->word=BLK(ADR(end)+1);
There’s a lot of magic happening here!
end is declared as address end[] and the code assumes that it’s the last global variable and therefore equal to the initial value of the segment break (I have not checked how this equality works) (also the declaration of the address type is another yikes)
Rcheat() is full-fat BCPL brainworms
/* the following nonsense is required
* because casts turn an Lvalue
* into an Rvalue so two cheats
* are necessary, one for each context.
*/
union { int _cheat;};
#define Lcheat(a) ((a)._cheat)
#define Rcheat(a) ((int)(a))
/* heap storage */
struct blk {
BLKPTR word;
};
both of those quotes from https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mode.h
/* stack */
#define BLK(x) ((BLKPTR)(x))
#define BYT(x) ((BYTPTR)(x))
#define STK(x) ((STKPTR)(x))
#define ADR(x) ((char*)(x))
Each day we stray farther from God’s light.