489 lines
44 KiB
Plaintext
489 lines
44 KiB
Plaintext
|
|
Episode: 2971
|
||
|
|
Title: HPR2971: World of Commodore 2019 Episode 2: Hacking GeckOS
|
||
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2971/hpr2971.mp3
|
||
|
|
Transcribed: 2025-10-24 14:05:59
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
This is HPR episode 2,971 for Monday the 23rd of December 2019.
|
||
|
|
Today's show is entitled, World of Commodore 2019 Episode 2, Hacking Geckos,
|
||
|
|
and as part of the series, Hobby Electronics, it is hosted by Paul Quirk,
|
||
|
|
and is about 49 minutes long, and carries a clean flag. The summer is. Glenn Holner explains
|
||
|
|
how he got Linux running on a Commodore 64.
|
||
|
|
This episode of HPR is brought to you by Ananasthos.com. Get 15% discount on all shared hosting
|
||
|
|
with the offer code HPR15, that's HPR15.
|
||
|
|
Better web hosting that's honest and fair, at Ananasthos.com.
|
||
|
|
Hello, good people of Hacker Public Radio. This is Paul Quirk, and I've returned with my
|
||
|
|
second episode of my World of Commodore mini-series. This episode features a presentation by Glenn
|
||
|
|
Holmer, a retired Java programmer in Linux Amin, who lives in Milwaukee, Wisconsin, USA.
|
||
|
|
He has a web page at lionlabs.org, and on December 7th, 2019, he was at World of Commodore
|
||
|
|
to tell us how he got Linux running on a Commodore 64. Pictures of this presentation
|
||
|
|
are available at my non-commercial, personal website at peakwork.com. This presentation
|
||
|
|
included visuals that are not available in this audio podcast. If you'd like to see
|
||
|
|
and hear this and other World of Commodore presentations, I recommend you go to the Toronto
|
||
|
|
Pet Users Group YouTube page. That's Toronto Pet Users Group, spelt as one word without
|
||
|
|
spaces, and the word users is plural. A link to this YouTube channel will be available
|
||
|
|
in the show notes. And so, with no further ado, I present you Hacking Gecko S by Glenn
|
||
|
|
Holmer. Hi, all. I'm Glenn, and I'm going to talk about Gecko S, which is the Unix
|
||
|
|
like operating system for Commodore 64, and a couple of the other Commodore machines. I'm
|
||
|
|
a 64 guy, and my interest is programming languages and operating systems. I've got a
|
||
|
|
good collection, a lot of it's on my website there. And I've talked a lot of the Commodore
|
||
|
|
shorts. I talk every year at DCF Midwest, and I've spoken at the Las Vegas, one of
|
||
|
|
Las Vegas shows, the old C4 show. And of course, I've spoken at the premier Commodore
|
||
|
|
conference, which is of course World of Commodore here in Toronto. Although I do have to say,
|
||
|
|
Father, forgive me, it has been five years since my last World of Commodore. So I don't
|
||
|
|
know how many Hail Jack Travelles, I'll have to say for that. And most of the talks
|
||
|
|
I've given have been about programming languages. Although I've talked a couple of times about
|
||
|
|
operating systems, but it's always been GS. So I said to myself, you know, there are other
|
||
|
|
operating systems out there for the Commodore 64, and I should probably learn one and share
|
||
|
|
some knowledge about it. And so I looked through my collection and I decided I was going
|
||
|
|
to talk about GACO-S, which turned out to be a really good choice because of course this
|
||
|
|
year is the 50th anniversary of Unix, which of course is like Annis rich and Gantan
|
||
|
|
Thompson, the party hats on. And nice machine, PDP 11 Model 20. It's a pretty big honking machine
|
||
|
|
there even for the early versions of Unix, right? So if you look at that, and then you
|
||
|
|
think to yourself, if Unix on a Commodore 64, well, you might be forgiven if you had a reaction
|
||
|
|
like this. But let's stop and think about it. Is it really that crazy? Let's, you know,
|
||
|
|
you're not, you're, let's face, you're not going to get salirous or linux or BSD or anything
|
||
|
|
like that running out of Commodore 64. But you might get something like the earlier Unix
|
||
|
|
is that weren't quite as large as the modern ones are. So let's look at the machines that
|
||
|
|
the early versions of Unix ran out. And by the way, these numbers come from Brian
|
||
|
|
Kernahan's new book on the history of Unix, and Betty Redden had. Yeah, if you haven't
|
||
|
|
read it, go out and get it. It's a great book. But the first version of Unix was written
|
||
|
|
on a PDP 7. I think it's 16 kilobytes of memory. Now that's not exactly the exact number
|
||
|
|
because the machine had 18 bit words and so forth. But I didn't think about that for a
|
||
|
|
second, right? And then about a year later, they ported it to C-Langwoods and they ran
|
||
|
|
it on that big conkin PDP 11 you just saw was 24 K. Good Lord. Wow. On a Commodore 64, we have,
|
||
|
|
well, 64 K. Yeah, okay. We're covered in the memory department, right? How about processor speed?
|
||
|
|
Well, that's a little harder to compare because the machines are really very different than
|
||
|
|
there's, it's, you can't really make an Apple's to Apple's comparisons. But from the research I
|
||
|
|
did, I got the impression that they really are comparable in speed between a Commodore 64 and
|
||
|
|
PDP 11, but somebody by contradicting online, I'm sure, but at least it's in the ballpark, right? So
|
||
|
|
memory, processor speed? Yeah, not that far away. However, the CPU itself, that's where the comparison
|
||
|
|
kind of falls down because there are three big differences between the PDP 11 and a 6510.
|
||
|
|
First of all, the PDP 11 had a user mode and a kernel mode. So there was some protection when
|
||
|
|
the kernel was running that user programs couldn't stop all over it. And of course, there's nothing
|
||
|
|
like that on a 65 or two. We don't have, you know, ring zero or ring three or anything like that.
|
||
|
|
And second of all, the PDP 11 had eight 16-bit general registers.
|
||
|
|
Okay, what do we got on a 65 or two? We have these three little tiny 8-bit registers, right?
|
||
|
|
A cumulative X index, Y index, and those are not general registers. They all answered
|
||
|
|
the different instructions, right? So yeah, the code is going to be difficult. And the third thing
|
||
|
|
of course is the stack. PDP 11 had a register that said where the stack is. Which is what you
|
||
|
|
need for multitasking because of course, that three program has to have its own stack.
|
||
|
|
So it's a simple matter to change the value in that register and say, oh, well, now the stack is
|
||
|
|
over here. Let's go over and run this program, right? Nothing like that on the 65 or two. Of course,
|
||
|
|
where the stack is always at 0100 and there's no way to change it. So the coding is going to be
|
||
|
|
a lot more complicated. But as far as resources are concerned, it's not that crazy. It's not that
|
||
|
|
crazy an idea. So let's talk a little bit about the ECHO-S starting with this history. How many
|
||
|
|
people here know who Andre Fushat is? He's the guy who wrote ECHO-S. I see a few pants going up.
|
||
|
|
I would expect more. But Andre of course is known particularly as an expert on the older
|
||
|
|
machines like the pets and so forth. And I would expect that at the Toronto pet users group,
|
||
|
|
there would be people to know who he is. But anyway, Andre works for IBM over in Germany.
|
||
|
|
And he originally wrote ECHO-S to run on a machine that he built himself. He built a 65 or two
|
||
|
|
machine. And that machine had a memory management unit and supported up to a megabyte of memory.
|
||
|
|
So it didn't have quite the restrictions that you would see on, for example, a Commodore 64.
|
||
|
|
But he did later port it to run on some of the Commodore machines. It'll run on a pet,
|
||
|
|
even a 32k pet. It'll run on an 82.96, which of course is the most beautiful machine ever created.
|
||
|
|
And it'll run on a Commodore 64, which is what I'm going to talk about. So as I talk about the
|
||
|
|
details of this, just bear in mind that they might be slightly different from one version to another.
|
||
|
|
Now, development on ECHO-S is extremely actively, especially within the last month or so.
|
||
|
|
And I think it might be partly my fault that this happened because as I was studying ECHO-S and
|
||
|
|
learning it and preparing for the first presentation I gave at BCF Midwest in Chicago, I was corresponding
|
||
|
|
with Andre. And I was asking questions and stuff. And every so often he'd say, well, I really
|
||
|
|
should get back into ECHO-S. Well, he has. And everything is changing really fast. If you look at
|
||
|
|
the commits on GitHub, there's just this long list of the things that have been changed and improved
|
||
|
|
and added. So the source is GPL. It's freely available. It's on GitHub. The other coordinates
|
||
|
|
on it is repo. So if you want, you can check out the latest branch or the latest stable release
|
||
|
|
and build it yourself and run it on your own machine. It's trivially easy to build,
|
||
|
|
well, the serving Linux it is, but it's really not hard to build it at all. In fact, when I do my
|
||
|
|
demo, I'm going to do a clean and build with the entire operating system before and you won't
|
||
|
|
believe what fast it is. So let's, oh yes, I have one more picture here. This is one version of
|
||
|
|
the machine that Gekos originally was written to run on. Wouldn't you love that or something
|
||
|
|
that looked like that? I love that picture. And this is the one with the MMU and supporting
|
||
|
|
megabyte of memory. Anyway, let's now talk about the features of Gekos. Now, looking at all the
|
||
|
|
stuff on this list, again, you might be forgiven. If your mind goes back to that other slide and you
|
||
|
|
start thinking, are you crazy? But honestly, God, it's got all these things and I'll be
|
||
|
|
demoing most of them in just a minute. First of all, Gekos is a preemptively multi-passing operating
|
||
|
|
system. It really is. It's not a, you know, it's not some trick or anything. It's really
|
||
|
|
preemptively multi-passing. It's got a scheduler that runs at interrupt time based on a timer interrupt.
|
||
|
|
In fact, not only is it multi-tasking, preemptively multi-tasking, but it's got task priorities.
|
||
|
|
The kernel has a nice API so that you can drop your priority and let somebody else run more.
|
||
|
|
It's even got multi-threading. It's a, by default, every thread, every process, every task that is
|
||
|
|
has one active thread, but you can start other threads, or you can just fork into tasks.
|
||
|
|
It's got virtual consoles. Now, Linux users are probably familiar with this. On Linux, if you
|
||
|
|
were to control all DEF1, it drops you down to a full-screen console and you can go control all DEF2 and
|
||
|
|
so on. Linux users usually ships with a half a dozen consoles. There are four on Gekos and you
|
||
|
|
can just tap F1 to cycle between it. It's got signals. One process can send a signal to another
|
||
|
|
process. It's got semaphores, which are very important in Gekos because of the lack of hardware
|
||
|
|
protection. So you'd have semaphores that are defined by the operating system that refer to,
|
||
|
|
for example, a certain area of memory, or a certain device, or the serial lesson general. A lot
|
||
|
|
of the kernel APIs require you to lock a certain semaphore first before you call an API so that nobody
|
||
|
|
gets, nobody else gets in there and does something you shouldn't do. Again, that's because there's
|
||
|
|
just no protection against this kind of thing on the 65-2. The shell has both background and
|
||
|
|
redirection. I'll be showing those. It's got piping. Piping as far as I can tell was broke for a long
|
||
|
|
time and I'm really just submitted some patches to get it to work again, but that was like literally
|
||
|
|
within the past couple days and I think it still has an issue with certain programs, so I won't
|
||
|
|
be showing that, but I'm sure it'll get fixed within the next few days. It's got environmental
|
||
|
|
variables. I'm not going to show that either, but there's a single environment on the commoner 64
|
||
|
|
version as opposed to an environment per task. And then it has a relocatable file format, which is
|
||
|
|
something that Audrey came up with. And of course, that's very important in a multitasking operating
|
||
|
|
system because you don't know where your program is going to load. Your program might load here
|
||
|
|
here today and tomorrow there might be something else running there and it loads over here.
|
||
|
|
So you can't have any absolute addresses and you're executable. What happens is when the system
|
||
|
|
loads a program into memory before it runs it, it does an address fix up based on the load address
|
||
|
|
so that all the addresses match up. So that's very important and that'll come up again later in the
|
||
|
|
discussion. So having set all this wonderful stuff and brag about all the stuff that Gedguis can do,
|
||
|
|
I guess I better put my money where my mom is to do a demo. So I hope you don't mind,
|
||
|
|
I'm going to do the demo using rice, but Leap and I worked it out so that we're going to have a
|
||
|
|
describe sound. So it's going to be close, but not a real machine. The thing is if you're doing
|
||
|
|
operating system work on a commoner 64, you're pretty well going to have to use cross-evolvement
|
||
|
|
tools and amulators any week because it's just too unvealed the other ways. I'm normally very
|
||
|
|
disapproving of that sort of thing but you know all bets are off of the operating system.
|
||
|
|
So here's what I'm going to be showing and like I say this is a very recent build of Gedguis,
|
||
|
|
it's not the most recent build because I had to cut it off. I think Monday or so
|
||
|
|
because things were changing so fast I could just need this. I needed to know what version I was
|
||
|
|
going to be running. Yeah and here's all this stuff I'm going to be showing. The highlight is going
|
||
|
|
to be most of this stuff has been in Gedguis for years now, but the highlight is going to be the
|
||
|
|
new PS and kill commands and I'll show how those were developed and how they weren't about that.
|
||
|
|
So let's go over here and I've got vice running. So I'm going to actually
|
||
|
|
know I said I was going to build it from scratch didn't I? So let's do this and then let's do this.
|
||
|
|
I've got a little script I use and I'm going to do a complete clean and build of the operating
|
||
|
|
system and then bring it up in the vice monitor. That should take a long time, right?
|
||
|
|
Or not. That was it. Now when you start get OS there's a basic loader that loads a large
|
||
|
|
kernel image and then it loads a little tiny machine language like you're like this. Then it loads
|
||
|
|
a little tiny machine language stuff and passes control to it and that little stub disperses the
|
||
|
|
kernel image into upper memory above below the IO layer and then it starts it up and the magic
|
||
|
|
begins. Here we go. There is our boot screen so now we have a real a for really real
|
||
|
|
unique slight operating system running on a pretend Commodore 64. Notice when it starts up that
|
||
|
|
there are five things starting. There is init. There are two file system device drivers. There's
|
||
|
|
one that controls the devices and one that's specific with the IEC bus and then there are two
|
||
|
|
shelves. The one says shell and the second one says LSH which stands for library shell because it's
|
||
|
|
as a standard library. That older shell is considered more or less obsolete and it's not really
|
||
|
|
supported anymore but it still has for a tad until the features that weren't in the new shell
|
||
|
|
which is the one that we're looking at now. So that stuff is gradually being ported over to
|
||
|
|
the new shell and I think at some point that over one is going to be deprecated. But where is
|
||
|
|
that older shell? We're only seeing one of course. I don't remember I said it has virtual
|
||
|
|
consoles right so if I tap F1 there it is. There's the other shell. That's the old one. Nothing
|
||
|
|
on three, nothing on four so let's go back to one. And then older shell they're both loaded
|
||
|
|
at boot time and that older shell actually includes a built-in machine language. You can imagine
|
||
|
|
that it's using a lot of memory. So that's not a small piece of code name.
|
||
|
|
But let's go back to that first shell and I want to show you that GECOS has a lot of the things
|
||
|
|
you would expect in a Linux-like operating system starting with a real and of course you can do
|
||
|
|
something like this. And there you go. The file sizes of course are actual number of bytes used
|
||
|
|
on the disk, not the file size itself. It's a number of sectors used times 256. And you know it even
|
||
|
|
has, I'm not sure I'm going to device this would be applicable but it's got you can put more
|
||
|
|
else on it and get a display with more stuff. And this is kind of like the full-mod
|
||
|
|
version of LS and we'll see if yeah. I'm a 1540 watercolor so this doesn't even apply.
|
||
|
|
So you can also do something like for example this does what you would expect.
|
||
|
|
Okay, so those are going to be missing my cat. He's the best cat a boy ever had. He's never ever
|
||
|
|
known. And remember I said it has a redirectional whistleboard.
|
||
|
|
Okay, you hear the disk drive running because it's ready to file out. Nothing came out on
|
||
|
|
standard output. And of course if we want to see where the output went we can count that file.
|
||
|
|
And the output wouldn't exactly where we would expect it to go. So you know you can look through
|
||
|
|
the directory and play around with some of the other things it's got. As of very recently we
|
||
|
|
like the past few weeks it's now got a more command. It's got a WC command word count. So there's
|
||
|
|
a lot of other stuff. But I'd like to show some demo programs that I wrote for Gekos that are
|
||
|
|
showing the more internal features of it that I was described before. And there are three little
|
||
|
|
demos all of which involve two programs. The first program is going to fork a second program
|
||
|
|
when it starts and then there's going to be some interaction between those two programs.
|
||
|
|
So the first one demonstrates forking and multitasking. So I have these two programs.
|
||
|
|
This program when it starts up is going to fork a second program and then second program being
|
||
|
|
forked. It's going to start flashing the border slowly. Well you see the first program is still running.
|
||
|
|
Eventually the first program ends, second program is still running and eventually the second
|
||
|
|
program ends. So you can see that the multitasking is very smooth. We had a constant pulsing of the
|
||
|
|
border when it was changing colors and everything. So everything the multitasking works extremely well.
|
||
|
|
Second demo is signal passing, sending a signal from one process to another.
|
||
|
|
So this first program, the two programs are six send and six receive. The first program
|
||
|
|
works the second program and when the second program starts, he's going to register a signal hand
|
||
|
|
alert. It says setting mask there and it just goes off the top. But the first program mean title
|
||
|
|
printed a message saying hit a key when you want me to send a signal. And then that second program
|
||
|
|
he's just going in the timer loop waiting for that signal to be sent. So if I hit a key,
|
||
|
|
that first program sent sig user one and then ended and the second program received the signal.
|
||
|
|
So that has all kinds of interesting possibilities. There was a guy at the Chicago store who said,
|
||
|
|
I'm going to write a battleship, he uses signal passing to get to do the stuff.
|
||
|
|
Then there are the third demo is the semiforce and I talk about the importance of semiforce. So
|
||
|
|
here's an example of that. First program, when he starts up, he's going to lock an arbitrary
|
||
|
|
semiforce named sendem. Then he's going to report that second program called sem wait.
|
||
|
|
And of course, the first program says, by the way, hit a key when you want me to free it. But meanwhile,
|
||
|
|
he's got a lock on that semiforce. And the second program says, well, okay, I'm waiting because the
|
||
|
|
second program is trying to do the same thing. He's trying to lock that same semiforce. But of course,
|
||
|
|
he's going to get an error message saying, you know, that semiforce is in use. So when I hit a key,
|
||
|
|
the first program frees that semiforce and then ends. And when the second program comes up and gets
|
||
|
|
his slice and gets a chance to run again, he's going to try again. And this time he did acquire the
|
||
|
|
lock. And of course, when he's done, he's reased the semiforce and ends. So if you're writing programs
|
||
|
|
for gecoest that involves semiforce locking, make sure you release the semiforce afterwards. Otherwise,
|
||
|
|
there will be pain and suffering. So those are the demos that I wanted to show, except that there's
|
||
|
|
one more demo. That forking and multitasking demo, there's another version of that demo. Because
|
||
|
|
when I first got that running, I was so excited that I actually made a video of it. I posted a link
|
||
|
|
to the video at IRC and leaves all that video. And he said, well, it's all well and good. But
|
||
|
|
you really want to do his background, the whole demo, and then take a directory listing while it
|
||
|
|
was running, right? And my reaction was basically, you know, are you crazy? But I thought, you know,
|
||
|
|
what's the cap, and I should try it, right? And with gecoest, you'll see that it happened over
|
||
|
|
and over again. You might come up with some crazy idea, think, well, I wouldn't work, but you try
|
||
|
|
it, and it does work. It happens all the time. So I'm going to do a slightly different version of
|
||
|
|
what I call the schema demo. And instead of taking a directory listing, I'm going to ask for a
|
||
|
|
process list, which is a good segue into this new PS token that we have. So here's the forking
|
||
|
|
demo again. And this time, I'm going to background it. And when I get my cursor back,
|
||
|
|
I'm going to ask for a process list. So they're forking is running, the second program is flashing
|
||
|
|
the board, and we have a process listing, and then one by one, the other programs they have.
|
||
|
|
This guy's still running. All right, so we had, and I don't know what the error message is,
|
||
|
|
something that came up recently. It doesn't hurt anything right now, but I'll figure it out.
|
||
|
|
And anyway, look at this process list. This is a thing of beauty right here.
|
||
|
|
We have on the left-hand column, the PID, the process ID, and as it turns out, the process ID is
|
||
|
|
actually an index into the task table. So by looking at it, we can see that the task table has 12
|
||
|
|
by entries, because it goes up to 12 every time. And then in the second column, of course,
|
||
|
|
we have the name of the process, which you need to know. And then you have, and by the way,
|
||
|
|
that name is new that didn't used to be there, then there's the exact address, which is also new,
|
||
|
|
and you have to go to the exact address of the program to debug it. Because remember before,
|
||
|
|
I was talking about how you have relocatable programs, and you don't know what the addresses
|
||
|
|
of your routines are until the program gets loaded and relocated. So you might have, you know,
|
||
|
|
say you have a routine called, you know, my Groovy routine, and you want to put a break point on it.
|
||
|
|
And you assemble your program, and you look at the listing, and it says, well, my Groovy routine is
|
||
|
|
at 0100. Well, it's not at 0100. It's at offset 0100 from the beginning of the program.
|
||
|
|
So you have to take the loaded address of the program, add the offset, and that's where you
|
||
|
|
sit at break point. So you need to know the exact address. And again, that's something new.
|
||
|
|
Next column is a number of active threads. A number of body fault. I said that every cast has one
|
||
|
|
active thread. And then that next one is really interesting. I love that next column. It's
|
||
|
|
parent PID. So the first one in it, of course, is me, it was the primary processes. And he really
|
||
|
|
has no panic. He gets started up by the kernel in root time. So he's got a parent of FF.
|
||
|
|
And remember when we saw Gecko as starting, and there were five things that started up in it,
|
||
|
|
two file system device drivers and two shells. So we can see that those are the first five entries.
|
||
|
|
And those second four all have a parent of 0, which means they were started in turn by in it.
|
||
|
|
Now we see that 3-0 is the shell, the one we're looking at. And I started forking from the
|
||
|
|
command line. So forking has a parent of 3-0, which is the shell. And forking, forked, forked,
|
||
|
|
and forked therefore has a parent PID of 3 Charlie. That makes sense. And then when I got my cursor
|
||
|
|
I typed PS at the command line. So PS has a parent of 3, the shell, not 3-0. So that is very
|
||
|
|
interesting information to have. SM is the signal mask for passing signals. So it's what signals
|
||
|
|
of program is prepared to respond to. And SIG A is the signal handler address,
|
||
|
|
another is the address that gets jumped to when the signal was received. Those last four are
|
||
|
|
all the same because, and I just learned this, the standard library actually multiplexes those,
|
||
|
|
and they all go to the same place and the fans off from there. And then of course we have the input
|
||
|
|
output in there. So I'm going to talk the deck of the last part of this talk is how we got the name
|
||
|
|
and the executive address in there, which didn't used to be in there before. And I'm going to take
|
||
|
|
a one-slade detour to show you the kill program, which was in the old shell too, but it's got a
|
||
|
|
few more features now, and I know what I'm going to do before it. And I got it accepted into the
|
||
|
|
kernel, into the master branch, and I'm very excited about that. So what I'm going to do is,
|
||
|
|
I'm going to go over here, and I'm going to start up the second half of that signal passing
|
||
|
|
bell. This is the program that sits here waiting for somebody to send to the signal and just goes
|
||
|
|
on the loop going, I'm here, I'm here, I'm waiting, I'm waiting, let's go back here. Now who knows
|
||
|
|
what the kill command does? Yes sir, kills a process. And put in the dumps cap and go sit by the
|
||
|
|
principal's office, sir. Sends a signal exactly. Now by default it sends a signal that will probably
|
||
|
|
kill the process that's receiving the signal. It sends by default a signal. And that may not kill
|
||
|
|
the process, depending on if it's going wild, it may not kill it. So in that case you might want
|
||
|
|
to send a signal kill, which of course is signal number nine, which is where we get the expression kill
|
||
|
|
dash nine, which even little girls who go to Jurassic Park know how to use. So I, the original
|
||
|
|
version of kill in Gecko has just did a kill, and I changed it so that it could send any arbitrary
|
||
|
|
process. So let's go over here and look. Oh, yep, still waiting to go. So let's send him a signal,
|
||
|
|
but first we need to know what his PID is. So we'll take a process listening.
|
||
|
|
And we'll see that there is Sig received. He's had three Charlie. So I'm going to send
|
||
|
|
it. I'm going to set a sig break signal to process three Charlie.
|
||
|
|
Well, let's get over there and watch this happen. I think those consoles wonderful.
|
||
|
|
And we'll see that, in fact, he did receive a signal one zero, which happens to be sig break.
|
||
|
|
Great, work as expected. Now I'm going to start him up one more time.
|
||
|
|
And this time, and he's going to have the same PID. He'll get the same slot over again.
|
||
|
|
And now I'm going to send him a kill dash nine. Now, as it happens, nine is not the number for
|
||
|
|
sig kill in Gecko's. In fact, sig kill is not as implemented in Gecko's, but that's okay.
|
||
|
|
Kill dash nine is tradition, right? So yeah. If you send him a kill dash nine,
|
||
|
|
well, let's watch and see what happens.
|
||
|
|
Boom. He's got a fork and he never even prints a message saying I got a signal because he
|
||
|
|
didn't get a signal. We just got his head chopped off. So that's the new stuff that's in
|
||
|
|
Gecko's. This PS and kill man. And now comes the kind of heavy duty part of the talk where I
|
||
|
|
talked about how we got there, how we got those, those new fields. So to understand how the name
|
||
|
|
and the process, the name and the exact address were added, we have to understand first how the
|
||
|
|
PS command works in Gecko's. So here's the old one, first of all. This is from the old shell,
|
||
|
|
and this is an earlier build of Gecko SS 2.09 release that came out in 2013, I think.
|
||
|
|
What's wrong with this picture? Well, first of all, we don't have any names. Well, you have one
|
||
|
|
name, but what's at PID zero? I guarantee you it's a net. I guarantee you it's a net, right? It's
|
||
|
|
not, it's not the challenge in it. So there's something there that could be improved and we don't have
|
||
|
|
the start address of each process. Like I said, if you want to the start address,
|
||
|
|
you can't really do meaningful debugging. There are other ways around that, but they're a little
|
||
|
|
quite big. So let's talk first about how the PS command works. Now, all this information that
|
||
|
|
PS printed out comes from the kernel's task table, but it's really not appropriate for an end user
|
||
|
|
program like PS to go stickiness fingers in the task table. That's kind of forbidden fruit,
|
||
|
|
doesn't work. The kernel shouldn't, you know, you should, you shouldn't be sticking your fingers
|
||
|
|
in the kernel's data structure, basically. But on a 6502, there's no way to prevent that.
|
||
|
|
Your program could, by adding a right include files, figure out fairly easy where the task
|
||
|
|
table is, but you shouldn't do it. You can't prevent it, but you shouldn't do it. So what happens
|
||
|
|
is that there's a kernel API called GetInfo, and that's what PS calls. PS calls into the kernel,
|
||
|
|
and he calls GetInfo, and GetInfo says, okay, I'm going to look at my little task table here. He
|
||
|
|
grabs information and he builds a table someplace for PS to read. Well, that's part of the story.
|
||
|
|
The place he builds that table is called the program communication buffer or PC buff for short.
|
||
|
|
Remember what I said about semaphores? You could have other processes that are, that are making
|
||
|
|
kernel calls that use that PC buff at the same time. That would be a bad thing, right? So what
|
||
|
|
really happens is the first thing PS does, he locks the semaphore that refers to the PC buff.
|
||
|
|
Then he calls into the kernel, he calls GetInfo, the kernel looks in his task table,
|
||
|
|
builds a table in the PC buff, PS reads it, and prints the results for screen. So that's the way it
|
||
|
|
works. Now, how do we get the name and the start address from the task table into the PC buff?
|
||
|
|
Well, I looked at this, and I thought to myself, I bet I can call it that. You know what? I like to do
|
||
|
|
this, but I'm still pretty leery of the Gekos kernel, because it's quite complex. It's really
|
||
|
|
quite complex, and so I thought to myself, maybe I could add this stuff by just changing GetInfo
|
||
|
|
and the way it gets in forward, and not actually touching the rest of the kernel itself.
|
||
|
|
And that would make it easier, right? So if you've ever done any amount of program,
|
||
|
|
you know that that kind of thinking invariably ends up with something that's 10 times as complicated
|
||
|
|
as what you originally wanted to do. But that's what I did. So I thought to myself, okay, I've got
|
||
|
|
two classes of programs I want to get the name for. One is the standard library programs that are
|
||
|
|
started by the shell, and the one is those five programs that we saw started by the kernel
|
||
|
|
when it started up, the voice drivers, the shells, and the end. So for the standard library programs
|
||
|
|
I did little digging, and I found that in the task table, one of the entries is a pointer to another
|
||
|
|
table. It's a per-processed table that's used by the standard library, and it contains them on
|
||
|
|
other things the name of the program. So I'm like, God, wow, that was easy. I'm all free.
|
||
|
|
All you got to do is when you call Gekos, he follows that link to the standard library's table,
|
||
|
|
he pulls up the name, plops it in the new field, and the task table, and we're all good, right?
|
||
|
|
Well, not really, because just like user programs shouldn't be sticking their fingers in the
|
||
|
|
kernel's data structure, the kernel shouldn't be sticking to his fingers in the standard library's
|
||
|
|
data structure either. And that's one of the things about Gekos. It's written properly. Everything
|
||
|
|
is done right. You know, you could clutch your way around this like I was trying to do, but it's
|
||
|
|
not the right way to do it. The kernel, I mean there's a reason we call it the kernel, right? The
|
||
|
|
kernel means like the core, the seed of something, and it should be an entity unto itself and not
|
||
|
|
even care or even know about the standard library. It shouldn't even have to know there is a standard
|
||
|
|
library. So that's not a good idea. It works, but it's not the right way to do it. All right,
|
||
|
|
shot down on that one. Then we have, where we really went off the rails, we have in it,
|
||
|
|
and the device drivers and the stuff that gets started at boot time. Well, I had a look at how
|
||
|
|
the operating system starts. And the way it starts is that you have this big kernel image in
|
||
|
|
memory. And at the beginning, there's a header followed by one of these programs. Then there's
|
||
|
|
another header somewhere else followed by a program and another header somewhere else. And
|
||
|
|
they're in any arbitrary order. You can't control it order, they're in the end. But each one of
|
||
|
|
those headers points to the next one. It's a linked list, right? So I thought, well,
|
||
|
|
looking at those headers, I see that just what the name is in the header, FSDab, FSIEC,
|
||
|
|
and whatever. So I thought, well, if I walk through those tables, I can just grab the name out of
|
||
|
|
there and I'll be good, right? It doesn't work. It doesn't work. And the reason it doesn't work
|
||
|
|
is that the kernel has a, well, it works, but the kernel has a fairly complicated way of going
|
||
|
|
through things. The question is, how do you get the right one of these programs with the right
|
||
|
|
process ID? And the only way I could think of to do it was to walk through those tables in the same
|
||
|
|
order that the kernel does when it starts up. Now, one of the things in the header is a program type
|
||
|
|
byte, which is a bitmap, bitmap. And what the kernel does is it walks through there and it starts
|
||
|
|
certain programs in a certain order. I want to look, I want to start for a program that's of type
|
||
|
|
in it. I want to start a program that's of type file system, right? And it makes multiple
|
||
|
|
passes going through all these programs. So what you'd have to do is you'd have to go through
|
||
|
|
there the exact same order that the kernel start up does and make multiple passes, but if you do
|
||
|
|
it exactly the right order, the names you come up with will match up one to one with the process
|
||
|
|
ID. Oh, boy. Okay. At this point, I really off the rails because this is just not something
|
||
|
|
you should do. Andre looked at that code and he said, I can't look at that for quite some time
|
||
|
|
to figure out what you're even trying to do. So yeah, that works, but it's a filthy clutch.
|
||
|
|
Apart from which, if the way the kernel starts changes even slightly, that whole thing's
|
||
|
|
going to fall down on the space. So, okay, both types of programs that I was looking for the names
|
||
|
|
where I came up with solutions that actually worked or seemed to work, but it was just a completely
|
||
|
|
wrong way to go about it. And as it turns out, going about at the right way by making subtle changes
|
||
|
|
to the kernel, turns out to be much easier. And these are the patches that Andre did. And this is
|
||
|
|
what's in GeckoS right now. So, as it turns out, of course, every single process that starts on
|
||
|
|
GeckoS has to go through the kernel for API. Fork is what starts a new process. It allocates another
|
||
|
|
entry in the task table. It creates a stack. It does all this other kind of housekeeping and then
|
||
|
|
it passes control to the new process. And guess what? What are the parameters you passed a fork
|
||
|
|
among other things? A name and an executive rest. So, it's already there. The kernels already got it.
|
||
|
|
So, all the kernels got to do is plug that value into the new fields in the task table.
|
||
|
|
When it starts a program, right? Easy. It should be easy, right? No. And the reason that's not easy
|
||
|
|
is because standard library programs pull a little trick. They put a stream number in the first
|
||
|
|
bite of the file name field and the file name actually starts in the second place. So, if you let
|
||
|
|
that go, every standard library program would have an unpredictable character at the beginning of
|
||
|
|
the file name. But as it turns out, there's a very easy, and by the way, more on that
|
||
|
|
stream number, it's passing that way later. But as it turns out, there's a very easy fix to that
|
||
|
|
because the standard library was not using all the possible parameters that the fork routine takes
|
||
|
|
when you call it. And you could use one of those parameters to pass that stream number. So,
|
||
|
|
that works out okay. That was just all fairly straightforward. I looked at the code when it was
|
||
|
|
committed, and I was like, oh, why did I think of that? And then adding the ones for the kernel
|
||
|
|
programs, that's simple because they're already there, and they're already perfect. The only
|
||
|
|
exception being that in it originally actually went out of its way to put a null wipe in the
|
||
|
|
name field. But there's no reason to mention pipes in the world. Now, adding the exact address,
|
||
|
|
we've got the name thing solved. Adding the exact address, let's see. The exact address is also
|
||
|
|
passed to fork. So again, you could just plop it right in and it would work. All for the program
|
||
|
|
started by the kernel, that's true. But again, we have an issue with the standard library. Now,
|
||
|
|
this one's really crazy. Yes, the reason it doesn't, the reason it's not quite going to work with
|
||
|
|
the standard library is that the way the standard library starts a program is that it does the
|
||
|
|
little housekeeping stuff. It calls for it to create a new process. And then after that call,
|
||
|
|
it lobes the program from disk and path and relocates it and passes control to it.
|
||
|
|
What's wrong with that picture? How can it load and run the program if it's already called fork,
|
||
|
|
which starts the process? It hasn't even been loaded from disk yet. But here's how that's done.
|
||
|
|
Here's the code that in the standard library, which is set everything up and called fork. And as
|
||
|
|
a started address, he passes the code a little bit further out in the standard library, which does
|
||
|
|
the loading and the relocation. So he calls for fork sets up a new process and everything and then
|
||
|
|
passes control to it with the address given, but the address given is within the standard library,
|
||
|
|
which is the routine that does the loading and the relocating. But as far as the kernel is concerned,
|
||
|
|
the new process is already running except that it isn't because it's the standard library. But once
|
||
|
|
he loads the program, relocates it, now he knows the started address, he passes control to it,
|
||
|
|
boom, here we go. Oh, what this is great. How wonderful he went, he was some code, right at that point
|
||
|
|
when he's done loading and he's about to pass control because now he knows the started address.
|
||
|
|
Fine, plug it right into the pass table. No, the standard library mustn't stick his fingers into
|
||
|
|
the kernel's task table, right? Again, we have that problem. So the solution to that one turn out
|
||
|
|
to be that Andre added a new API to the kernel called setinfo. Now we have to get info and we have setinfo
|
||
|
|
and setinfo allows the active task to set its own started address in the task table.
|
||
|
|
And remember, the active process at that point was really not the process that's going to start.
|
||
|
|
It's still the standard library which is loading because it's called fork with its own address and fork
|
||
|
|
thinks the new process is starting and it gets this far, it knows the address, it plugs it in and then
|
||
|
|
it jumps to the program so it all works out anyways. I don't know if I explained that well or not but
|
||
|
|
this is pretty crazy stuff but this is the kind of stuff that you experience when you're when you're
|
||
|
|
dealing with something on the operating system. And even something like EchoS that runs on a fairly
|
||
|
|
small machine, there's a lot of complexity there but it was a lot of fun and there's the solution
|
||
|
|
we have a setinfo. So this is great stuff. This is wonderful stuff. And now that we have this PS
|
||
|
|
and kill, we can do almost anything because we can debug our programs beautifully. In fact,
|
||
|
|
it's a new goal to me into EchoS I think to call it because now all the things that have been on
|
||
|
|
a list can be moved forward. First of all, I think there's a little of anything that's still in
|
||
|
|
the old shell that's not in the new shell so it could probably be deprecated pretty soon. You just
|
||
|
|
have the new shell. You might still want to have two of them running, right? But you wouldn't have
|
||
|
|
to have that old shell with the machine language modern ability which by the way you can load from
|
||
|
|
disk even now. Another thing, what are some things we could do with EchoS? We could have better
|
||
|
|
support for CMD hard drive. So remember that long listing I showed you with the file timestamp
|
||
|
|
and everything? Well, CMD hard drive has a timestamp but get West doesn't know where to find it so
|
||
|
|
that would be interesting. The one that interests me most is imagine how many people are familiar with
|
||
|
|
the 50-41 ultimate? Two plus a lot of hands go on. Okay. That machine, as you know, has an ethernet port
|
||
|
|
and what might be a little less well known is that there is an API that you can call you,
|
||
|
|
you can push some registers and stuff and you can actually open a socket and talk to another
|
||
|
|
machine and you can write your own networking programs. Imagine a vice driver for the 50-41
|
||
|
|
ultimate networking capabilities within the EchoS. I don't know if I have the chops to do that
|
||
|
|
but I like to try. Another thing you may have noticed that the disk access is not particularly fast
|
||
|
|
in the EchoS. It doesn't of course have GIF you do have less but maybe there's a way to speed
|
||
|
|
that up and there are some other things involved to involve in buffering and those are known
|
||
|
|
issues that might get worked out later on. It's a big deal. And of course your project here,
|
||
|
|
what I found when I gave a talk on the EchoS in Chicago was that all these people can have
|
||
|
|
coming up to my table and say, oh wow, I could do that. You don't like the guy who said he wanted
|
||
|
|
around writing a battleship program. Imagine all the different stuff you could do.
|
||
|
|
So if you're interested in working with EchoS and writing your own programs for it,
|
||
|
|
if you know 65 or something, 65 or two assembly, it's not hard at all. If you look at those
|
||
|
|
demo programs I showed, all of the stuff that actually was happening in those like the forking
|
||
|
|
and the signal sending and the cell four locking and all that stuff, it's all just a few lines of
|
||
|
|
code and most of those programs are like waiting on a timer loop, printing stuff to the screen,
|
||
|
|
error hand learning all it's like 90% fluff and just a few lines of code. So it's really
|
||
|
|
easier write programs for GIF if you're interested. Have a look at it.
|
||
|
|
Here's the resources slide and I'm going to post these slides on my website right after you
|
||
|
|
back to my table. But the bottom one is interesting and that is the commentary that I wrote on the
|
||
|
|
internals of GIF which is not finished and will never be finished because there's so much to learn.
|
||
|
|
But this the name of course is a play on words from Professor Lyon's commentary on women's
|
||
|
|
right. So I wrote this commentary and it's a very detailed description of the internals of
|
||
|
|
GIF. Tell us about what happens when the operating system is started. It talks yeah I'll post this
|
||
|
|
on my site. It starts it talks about what happens when the operating system is started, how the
|
||
|
|
scheduler works, how programs get loaded by the shell and all those different stuff in
|
||
|
|
men's detail of file names are nine authors. So if you're interested in learning the internals
|
||
|
|
of GIFs, have a look at my commentary and that'll help you get a leg up and learn where wrongs
|
||
|
|
and probably go further back. Okay having said all that we come to a slide that says questions.
|
||
|
|
Does anybody have any questions about GIFs? Yes. Would it be even hypothetically possible to get
|
||
|
|
something like CC6502 building GIFs like relocatable images? Are you like the sea compiler?
|
||
|
|
You're talking about doing it in the sea. Yeah. The question was is it possible to write
|
||
|
|
programs in sea for GIFs using CC65? I guess all I can say is good luck with that.
|
||
|
|
It would require it would require CC65 to know how to generate an executable in that relocatable
|
||
|
|
format. That would be the main time. I guess it would. I don't know. The answer I gave
|
||
|
|
to Chicago. I got the same question to Chicago and the answer I gave is well real men quote me
|
||
|
|
somewhere. But yeah it's theoretically possible. Anybody else have a question?
|
||
|
|
What's the role of that? I see 128 portability there. Yeah that's another question that came up
|
||
|
|
and somebody asked about Atari and that and all this other stuff. Theoretically you could write
|
||
|
|
it for almost any 6502 program and if you look at the source code there's a directly called
|
||
|
|
ARCH. So there's ARCH C64 and ARCH PET and ARCH 8296 or whatever. There's also an ARCH
|
||
|
|
proto-sub directory that has basically like a clean slate version of what you would need to do
|
||
|
|
to port to a new architecture. But I don't want you to have any false hopes about that because
|
||
|
|
it would not be straightforward. It's certainly doable. But I have by the way complete
|
||
|
|
printout of the Ganko S source code back up my table heavily highlighted and penciled in with
|
||
|
|
markings and stuff like that. And if you have a look at that you'll see that it's just littered
|
||
|
|
with a lot of defines and if deaths and so on and so forth. So it's already fairly complicated
|
||
|
|
adding additional architectures while certainly possible. It would not be a small undertaking.
|
||
|
|
But yeah it's certainly possible. You could write a version for the 128 or whatever
|
||
|
|
machine is author. Anybody else? All right. In that case thank you very much for your kind of
|
||
|
|
tension ladies and gentlemen. I hope you enjoyed Glenn's presentation as much as I did.
|
||
|
|
Please tune in next week to hear Dr. Richard Emmer's presentation entitled Life After Commodore.
|
||
|
|
Until then, please drive safe and make sure to have fun.
|
||
|
|
You've been listening to Hecker Public Radio at Hecker Public Radio dot org.
|
||
|
|
We are a community podcast network that releases shows every weekday, Monday through Friday.
|
||
|
|
Today's show, like all our shows, was contributed by an HBR listener like yourself.
|
||
|
|
If you ever thought of recording a podcast then click on our contributing to find out
|
||
|
|
how easy it really is. Hecker Public Radio was founded by the digital dog pound and the
|
||
|
|
infonomican computer club and is part of the binary revolution at binwreff.com.
|
||
|
|
If you have comments on today's show, please email the host directly, leave a comment on the website
|
||
|
|
or record a follow-up episode yourself. Unless otherwise stated, today's show is released on
|
||
|
|
creative comments, attribution, share a light, 3.0 license.
|