TweetFollow Us on Twitter

Mixed Up Threads

Volume Number: 13 (1997)
Issue Number: 7
Column Tag: develop

Mixed Up Threads

by Andy Bachorski and George Warner

See if you can solve this puzzle in the form of a dialog between a pseudo KON (Andy Bachorski) and BAL (George Warner). The dialog gives clues to help you. Keep guessing until you're done; your score is the number to the left of the clue that gave you the correct answer. Even if you never run into the particular problems being solved here, you'll learn some valuable debugging techniques that will help you solve your own programming conundrums. And you'll also learn interesting Macintosh trivia.

KON So, BAL, I've run into a weird problem. I crash when I try to compile and execute a script using the AppleScript Open Scripting Architecture component from within a native PowerPC(tm) application.

BAL What's so weird about that? AppleScript hasn't been touched in years. It's bound to be showing its age by now.

KON Yeah, sure. Anyway, I've got an application that creates several threads.

BAL Now you're throwing the Thread Manager into the mix?

KON Look, can I just explain the problem? As I said, several threads are created, and inside each thread a string containing a valid AppleScript script is passed to the AppleScript component to be compiled and executed.

BAL This one's easy. You're using a single AppleScript component instance for all the threads. You need to have a separate instance for each thread for this scheme to work.

100

KON Wrong. Why don't you let me finish? Inside each thread we ask for and get an AppleScript component instance. Next we call OSACompileExecute to tell AppleScript to compile the script text. The thread terminates when OSACompileExecute returns.

BAL Hmm. If all you're doing in each thread is calling OSACompileExecute, how are the other threads getting time before the first one terminates?

90

KON Well, the AppleScript component lets you install an active function that gets called periodically during the compilation and execution of a script. Normally you'd call WaitNextEvent to give time to other processes, but here we call YieldToAnyThread to give the other threads time.

BAL D'oh! I'll bet when you install the active function, you're passing a ProcPtr, and not a UniversalProcPtr.

80

KON I don't think so. I create a new routine descriptor by calling NewOSAActiveProc before installing the active function.

BAL Well, then, the routine descriptor is getting disposed of before the AppleScript component uses it.

KON Get a life.

BAL I've got it! The AppleScript component is 68K code, and since threads must be created and yielded from the same instruction set architecture, you crash when yielding from the active function.

70

KON No, I've installed a PowerPC routine as the active function, so I am creating and yielding the threads from the same ISA.

BAL Sounds as if the AppleScript component just doesn't like to be threaded.

60

KON No, that's not it, because I can run as many threads as I like with a 68K application. The crash happens only when the application is compiled as a native PowerPC application. I told you it was weird.

BAL I guess that means AppleScript and the Thread Manager aren't compatible on Power Macs.

50

KON Nope. As long as I create only a single thread in the native application it works just fine. But with two or more threads, I crash with a bus error.

BAL Maybe it would help if we knew where it's actually crashing. Set a breakpoint just before calling YieldToAnyThread in the active function.

45

KON After setting the breakpoint, I see that it's crashing when the second thread resumes after its first yield.

BAL That's a strange place to crash. Let's see what's going on inside the thread. I'm going to assume that you're opening a valid component instance.

KON Good call, since the thread would bail if it didn't.

BAL OK, so set a breakpoint on the call to OSACompileExecute.

40

KON Now we see that when the first thread resumes after its first yield, OSACompileExecute returns immediately with errOSAScriptError (-1753). If I continue and let the second thread resume, I crash with a bus error upon entering the second thread.

BAL But you say everything is fine if there's only a single thread. I'll bet the AppleScript component's A5 world is getting trashed. Why don't you save and restore A5 around the call to YieldToAnyThread?

35

KON After I add a call to SetCurrentA5 before yielding and a call to SetA5 after yielding, there's no change. Still crashing, same place, same way. Now what?

BAL Must be an internal flaw in AppleScript. It was written before either the Thread Manager or Power Macintosh systems existed. I don't think it's up to the task.

KON And I say you're wrong. But it sure seems like someone is getting confused whenever our active function is called.

BAL I thought you seemed a little dazed.

KON And confused!

BAL Let's see what the AppleScript component looks like before and after it calls the active function. Does the application still have the DebugStr calls in it?

KON Yes, but that won't do us any good. By the time we hit the breakpoint, the active function has already been called.

BAL Then it's time to get our hands dirty with MacsBug.

KON I'll go get the protective gear.

BAL Very funny. Let's start by seeing if the stack is getting munged by the call to the active function.

KON I'm yours to command.

BAL OK, run the application until the first thread is ready to return from the active function; then step until we're back in the AppleScript component.

30

KON We're in the component, and here's what you see when you disassemble around the PC:

00725C18  MOVE.L     A4,-(A7)                | 2F0C
00725C1A  JSR        *+$1228     ; 00726E42  | 4EBA 1226
00725C1E  SUBQ.L     #$2,A7                  | 558F
00725C20  MOVE.L     D6,-(A7)                | 2F06
00725C22  JSR        (A3)                    | 4E93
00725C24 *MOVE.W     (A7)+,D7                | 3E1F
00725C26  MOVE.L     A4,-(A7)                | 2F0C
00725C28  JSR        *+$11BA     ; 00726DE2  | 4EBA 11B8
00725C2C  EXT.L      D7                      | 48C7
00725C2E  BEQ.S      *+$0010     ; 00725C3E  | 670E

BAL The JSR to the address in A3 is where the active function is being called. We need to break just before it's called.

KON Great, I'll set a breakpoint at the JSR instruction.

BAL Not so fast. We've already returned from the function, so we'll need to restart the application to be able to check the stack before and after the active function is called.

KON And?

BAL And after we restart the application, the AppleScript component might not be loaded at the same place. We need the offset of this instruction in the component.

25

KON I'll use the thing dcmd to find out where the AppleScript component is loaded. After entering thing "osa " in MacsBug, we see this:

Displaying Registered Components
 Cnt tRef# ThingName   Type SubT Manu Flags  EntryPnt
  #1 050009 (Not yet load... osa ascr appl 000001FE 007059A0

BAL This gives us the location of the AppleScript component, and if we subtract the caller address from stack frame, we have the offset we need to find the instruction again.

KON OK, I've got its offset. I've restarted the application and, after locating the AppleScript component again, I've set a breakpoint before the active function is called.

BAL Go until you hit the breakpoint; then dump memory from the stack pointer before and after the JSR to the active function.

KON Except for the return value from the function, the stack looks untouched. Now what?

BAL So the stack is untouched. OK, let's restart and take a look at the registers.

KON Which ones?

BAL Let's start with the PowerPC registers and make sure the Thread Manager is doing the right thing.

20

KON We do a register dump at the breakpoints set in the active function before and after YieldToAnyFunction is called, and the registers look the same. The Thread Manager is doing the right thing.

BAL This time we'll check the emulated registers. Set the breakpoint at the active function call, and check the 68K registers around the call.

15

KON Restarted the application, set the breakpoint...we're there. Here's the registers display before the active function is called:

68020 Registers
 D0 = 00000000   A0 = 0212E630
 D1 = 00000005   A1 = 007275DE
 D2 = 00000004   A2 = 022253E0
 D3 = 00000001   A3 = 021674A0
 D4 = 00000000   A4 = 0212E63C
 D5 = 0000006B   A5 = 02265520
 D6 = 00000000   A6 = 02156C9C
 D7 = 00070000   A7 = 02156C82

And here it is after the active function returns:

68020 Registers
 D0 = 00000100   A0 = 002E20D2
 D1 = 0000200D   A1 = 00000017
 D2 = FFFFF1F0   A2 = 0221C080
 D3 = 00000001   A3 = 021674D0
 D4 = 00000000   A4 = 0212E61C
 D5 = 0000006B   A5 = 02265520
 D6 = 00000000   A6 = 02156C9C
 D7 = 00070000   A7 = 02156C86

It doesn't look good.

BAL Well, we can ignore D0 through D2, A0, and A1, because they're scratch registers and don't need to be saved. And we know that A6 and A7 will change as the application runs. That still leaves a lot of registers that aren't what they should be.

KON So who's twiddling our registers?

BAL Let's do the drill one more time, but this time we'll look at the registers around the call to the active function for both threads.

KON I've stepped through the calls to the active function, again.

BAL And?

10

KON When we return to the AppleScript component in the first thread, the emulated 68K registers contain the second thread's values.

BAL That would explain why AppleScript is crashing. It gets back after the call to the active function, but when it tries to pick up where it left off, someone has changed its world.

KON Now we know what's happening, but not why it's happening. We need someone to pin this on.

BAL So far we know that everything's fine in a 68K application. And we're OK with a single thread in a PowerPC application, but when there's a second thread we've got problems.

KON Right. And since we know that the emulated 68K registers are changing behind AppleScript's back, it must be the Mixed Mode Manager's fault.

BAL I'm not so sure. The Mixed Mode Manager is only responsible for transitioning between ISAs and RTAs (runtime architectures). It's up to the emulator to maintain the emulated registers, which are stored in a single emulator context block. I think this is causing problems for the Thread Manager.

KON What are you talking about? The Thread Manager doesn't have anything to do with the emulated 68K registers. Besides, the application works just fine when it's compiled as 68K code.

BAL It does, but when you have a 68K application, you have 68K threads and a 68K AppleScript component. In this environment, the registers all get properly protected.

5

KON The Thread Manager saves registers regardless of the ISA or RTA of the application.

BAL Right, but I think what we have here is a nasty interaction between the Thread Manager and the 68K Emulator. The root of the problem is the single emulator context block where the emulated 68K registers live.

KON Let's see. Inside the thread the AppleScript component (68K) calls the active function (PPC code) which causes a mode switch. Now we're in native mode with the emulated registers lying dormant in the emulator context block. At this point the AppleScript component is assuming that the active function it just called will preserve any nonvolatile registers it touches.

BAL Next the active function calls YieldToAnyThread; the Thread Manager saves a PowerPC thread context and goes to the next thread. But the Thread Manager doesn't know anything about the AppleScript component needing the emulated 68K registers preserved during the thread switch.

KON So now the second thread gets control, and it fills the emulated 68K registers with its own values. Another yield happens, and we get back to the first thread. But the single emulator context block now contains register values from the previous thread.

BAL And since that's not what the first thread is expecting, it dies a terrible death. Let's throw together a little hack that we can use to test your theory. First create a couple of inline 68K routines that save and restore the registers.

static UInt16 SaveRegisterHack[] = {
    0x48d0, 0x1cf8,     // movem.l d3-d7/a2-a4,(a0)
    0x4e75              // rts
};

static UInt16 RestoreRegisterHack[] = {
	0x4cd0, 0x1cf8,     // movem.l (a0),d3-d7/a2-a4
	0x4e75              // rts
};

KON That's really skanky. I like it!

BAL Now we need some procedure information, so we can call these routines.

enum {
 uppRegisterHackProcInfo = kRegisterBased
  | REGISTER_ROUTINE_PARAMETER(1, kRegisterA0, SIZE_CODE(sizeof(Ptr)))
};

KON Check.

BAL Now in the active function add a call to SaveRegisterHack before calling YieldToAnyThread and a call to RestoreRegisterHack after the yield call.

long   reg68K[8];
CallUniversalProc((UniversalProcPtr) &SaveRegisterHack,
                   uppRegisterHackProcInfo, reg68K);
YieldToAnyThread();
CallUniversalProc((UniversalProcPtr) &RestoreRegisterHack,
                   uppRegisterHackProcInfo, reg68K);

KON Don't we need to create a UniversalProcPtr before calling the register hack routines?

BAL No. Remember, a 68K ProcPtr is a valid routine descriptor. Just call that sucker!

KON Cool!

BAL Here's where the rubber meets the road. Let's run the application now that we've got the registers protected.

KON Bingo. It ran all the way through without a crash. That proves our theory. You know, the problem is really that the Thread Manager was designed to function in a homogenous application context, but in a case like this we're abusing it with cross-ISA/RTA callback functions it doesn't expect. So it needs our help to keep everything straight.

BAL Too bad the hack we put together is so ugly. I'd never want to use something like that in my code.

KON You don't have to! Through special arrangements, BalKon Industries is able to offer on this issue's CD not one, but two, library routines you can link into your application to work around the active function problem, as well as a similar problem when installing send functions in a native application using the AppleScript component.

BAL Nasty.

KON Yeah.


SCORING:

80-100
And I'll bet your code compiles and runs the first try.
45-70
You're an asset to your company; ask for a raise.
25-40
Not too bad, but keep your resumé updated just in case.
5-20
At least you're honest.

Thanks to Eric Anderson, Bo3B Johnson, Jon Pugh, Quinn "The Eskimo!", KON (Konstantin Othmer), and BAL (Bruce Leak) for reviewing this column.


Andy Bachorski (andyb@apple.com) works in Apple's Developer Technical Support answering questions about Apple events, AppleScript, and the Thread Manager. In previous lives he worked as a Mac consultant and system integrator, sold insurance door to door, was a used-car salesman, wore almost every hat while working at an Apple dealer, programmed CNC machining centers, walked the high iron as an iron worker, and wrenched on cars at Sears. Lifetime highlights include marrying his wife Linda and being present for the birth of their children Andrea and Colin.

George Warner (geowar@apple.com) spends too much time searching for his wandering robot in the halls of Apple's R&D campus. He suspects the robot is jealous of his way-too-beautiful-to-marry-a-computer-nerd (but did) wife. Otherwise he's kept busy answering questions from developers about CFM and the Mixed Mode Manager in Developer Technical Support. Prior to his life at Apple, George shoved mainframes around at TRW and Digital and jumped out of perfectly good aircraft in the Air Force. Now he has a life (and a cute wife!).

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

ExpanDrive 5.4.6 - $49.99
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
Apple Pages 6.1.1 - Apple's word pr...
Apple Pages is a powerful word processor that gives you everything you need to create documents that look beautiful. And read beautifully. It lets you work seamlessly between Mac and iOS devices, and... Read more
Apple Numbers 4.1.1 - Apple's sprea...
With Apple Numbers, sophisticated spreadsheets are just the start. The whole sheet is your canvas. Just add dramatic interactive charts, tables, and images that paint a revealing picture of your data... Read more
Apple Keynote 7.1.1 - Apple's prese...
Easily create gorgeous presentations with the all-new Keynote, featuring powerful yet easy-to-use tools and dazzling effects that will make you a very hard act to follow. The Theme Chooser lets you... Read more
Espresso 5 - Powerful HTML, XML, CSS, an...
Espresso is back. For people who make delightful, innovative, and fast websites -- in an app to match. Espresso helps you write, code, design, build, and publish with flair and efficiency.... Read more
Vitamin-R 2.47 - Personal productivity t...
Vitamin-R creates the optimal conditions for your brain to work at its best by structuring your work into short bursts of distraction-free, highly focused activity alternating with opportunities for... Read more
Dash 4.0.3 - Instant search and offline...
Dash is an API documentation browser and code snippet manager. Dash helps you store snippets of code, as well as instantly search and browse documentation for almost any API you might use (for a full... Read more
Posterino 3.3.6 - Create posters, collag...
Posterino offers enhanced customization and flexibility including a variety of new, stylish templates featuring grids of identical or odd-sized image boxes. You can customize the size and shape of... Read more
Together 3.8.3 - Store and organize all...
Together helps you organize your Mac, giving you the ability to store, edit and preview your files in a single clean, uncluttered interface. Features Smart storage. With simple drag-and-drop... Read more
iClock Pro 3.4.9 - Customize your menuba...
iClock Pro is a menu bar replacement clock for Apple's default clock. iClock Pro is an update, total rewrite and improvement to the popular iClock. Have the day, date and time in different fonts and... Read more

Latest Forum Discussions

See All

Anime tactical RPG, War of Crown, comes...
If you're looking for another tactical RPG fix to go alongside your Fire Emblem Heroes campaigns check out Gamevil's newest, anime-inspired tactics RPG, War of Crown, which comes out tomorrow. [Read more] | Read more »
Fantasy MMORPG MU Origin adds new modes,...
MU Origin, Webzen’s highly popular fantasy MMORPG is getting ready to shake things up for the second time this year, as a new update makes its way to the Google Play and App Store from today. Introducing new systems, modes, and events, the land of... | Read more »
Blizzard is looking to hire a mobile dev...
A new thread on the popular video game rumor forum, NeoGAF, uncovered an interesting job listing over at Blizzard Entertainment. It appears the studio behindStarCraft, World of WarCraft, Hearthstone,andOverwatch is looking to bring on a new hire... | Read more »
Legend of Zelda meets Cooking Mama in ne...
Dungeon Chef is what happens when you mix the RPG elements (and style) of a Legend of Zelda game, with cooking elements. Although, now that The Legend of Zelda: Breath of the Wild also has cookingelements, so maybe the gameplay is not so novel.... | Read more »
ChordFlow (Music)
ChordFlow 1.0.0 Device: iOS Universal Category: Music Price: $6.99, Version: 1.0.0 (iTunes) Description: ChordFlow is a chord sequencer with a unique 4-track polyphonic arpeggiator, extensive chord library, MIDI out and Ableton Link... | Read more »
The Walking Dead: A New Frontier is out...
The newest season of Telltale Games'The Walking Dead is well underway. After the release of the third episode, "Above the Law" about a month ago, episode four, "Thicker Than Water" is hot and ready for more zombies and gut-wrenching emotional... | Read more »
Best games we played this week
Another week, another new wave of mobile games do dive into. We've dug through the list of apps that came out this week to tell you which apps are worth your sweet time. And while there weren't too many games this week, there were some big ones.... | Read more »
Vignettes (Games)
Vignettes 1.0.1 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.1 (iTunes) Description: Vignettes is a casual but unique exploration game without text or characters, where objects shapeshift as you spin them around... | Read more »
Get Me Outta Here is an 80s retro shoote...
Are you ready to fight some aliens? Because Crescent Moon Games has released the retro shooter Get Me Outta Here on iOS devices today. [Read more] | Read more »
Get a bunch of Apple productivity apps f...
If you're an Apple Mac owner, you're probably aware of the host of Apple productivity apps the company includes in all new Mac purchases. Apps like iMovie, Keynote, and of course, GarageBand. While you used to be able to also buy these apps... | Read more »

Price Scanner via MacPrices.net

HyperX Ships Pulsefire FPS Gaming Mouse, Winn...
Your reporter is a longtime fan of gaming mice for general purpose coomnputing use, finding them typically superior in comfort and performance. HyperX, a division of Kingston Technology Company, Inc... Read more
Penske Truck Leasing Unveils “Penske Fleet” M...
Penske Truck Leasing has introduced a free mobile app called “Penske Fleet” to benefit its full-service truck leasing and contract maintenance customers. The mobile app enables Penske’s customers to... Read more
DEVONthink To Go 2.1.3 For iOS Adds New Declu...
DEVONtechnologies has updated DEVONthink To Go, its iOS companion to DEVONthink for Mac. Enhancements and bug fixes in Version 2.1.3 include DEVONtechnologies’ new decluttering service for clipping... Read more
Use Apple’s Education discount to save up to...
Purchase a new Mac or iPad using Apple’s Education Store and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free: -... Read more
Apple refurbished Apple Watches available sta...
Apple is now offering Certified Refurbished Series 1 and Series 2 Apple Watches for 14-16% off MSRP, starting at $229. An Apple one-year warranty is included with each watch. Shipping is free: Series... Read more
15-inch Touch Bar MacBook Pros, Apple refurbi...
Apple is offering Certified Refurbished 2016 15″ Touch Bar MacBook Pros for $360 to $420 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 15″ 2.6GHz... Read more
13-inch MacBook Airs on sale for up to $150 o...
Overstock.com has 13″ MacBook Airs on sale for up to $150 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (sku MMGF2LL/A): $869.99 $130 off MSRP - 13″ 1.6GHz/256GB MacBook Air (sku... Read more
15-inch Touch Bar MacBook Pros on sale for $1...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $200 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more
15-inch 2.7GHz Touch Bar MacBook Pros on sale...
Amazon has 2016 15″ 2.7GHz Apple Touch Bar MacBook Pros in stock today and on sale for $150-$200 off MSRP. Shipping is free: - 15″ 2.7GHz Touch Bar MacBook Pro Space Gray (sku MLH42LL/A): $2599 $200... Read more
Apple now offering Certified Refurbished 13-i...
Apple is now offering Certified Refurbished 2016 13″ Touch Bar MacBook Pros for $270-$300 off original MSRP. An Apple one-year warranty is included with each model, and shipping is free: - 13″ 2.9GHz... Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Solutions Consultant - Apple (United...
# Apple Solutions Consultant Job Number: 56881986 Middletown, NY, New York, United States Posted: Apr. 17, 2017 Weekly Hours: 40.00 **Job Summary** As an Apple Read more
*Apple* Mobile Master - Best Buy (United Sta...
**489879BR** **Job Title:** Apple Mobile Master **Location Number:** 000402-Utica-Store **Job Description:** **What does a Best Buy Apple Mobile Master do?** At Read more
Music Marketing Lead, iTunes & *Apple*...
# Music Marketing Lead, iTunes & Apple Music Job Number: 56868140 Culver City, California, United States Posted: Apr. 17, 2017 Weekly Hours: 40.00 **Job Summary** Read more
Best Buy *Apple* Computing Master - Best Bu...
**498001BR** **Job Title:** Best Buy Apple Computing Master **Location Number:** 000356-Manassas-Store **Job Description:** **What does a Best Buy Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.