Threads Of The Past Mac OS

Posted on  by

Note: For a historical look at the threading architecture of Mac OS, and for additional background information on threads, see Technical Note TN2028, “Threading Architectures”. Thread Costs Threading has a real cost to your program (and the system) in terms of memory use and performance. Find helpful customer reviews and review ratings for Threads of the Past: Stories of Pioneer Women and Their Quilts at Amazon.com. Read honest and unbiased product reviews from our users.

  • PThreads are available on Solaris, Linux, Mac OSX, Tru64, and via public domain shareware for Windows. Global variables are shared amongst all threads. One thread can wait for the others to rejoin before continuing. PThreads begin execution in a specified function, in this example the runner( ) function: Figure 4.9. 4.4.2 Windows Threads.
  • How many other Mac users have noticed that if using an external Blu-ray drive with their Mac that they don't get a Blu-ray disc icon on their desktop if runing OS 11 Big Sur? I lnow I'm not alone and assume it a bug with the OS as opposed to being a purposeful omission on Apple's part, but I.

References:

  1. Abraham Silberschatz, Greg Gagne, and Peter Baer Galvin, 'Operating System Concepts, Ninth Edition ', Chapter 4

Mid 2007 model black 2.16 dual Processor 4gb ram Mac OS X I bought it used from my cousin about 2 months ago, he did a reset so it was basically new and it was in very good condition when I got it. Untill this problem it took only about 15 seconds for a complete start up.

4.1 Overview

  • A thread is a basic unit of CPU utilization, consisting of a program counter, a stack, and a set of registers, ( and a thread ID. )
  • Traditional ( heavyweight ) processes have a single thread of control - There is one program counter, and one sequence of instructions that can be carried out at any given time.
  • As shown in Figure 4.1, multi-threaded applications have multiple threads within a single process, each having their own program counter, stack and set of registers, but sharing common code, data, and certain structures such as open files.


Figure 4.1 - Single-threaded and multithreaded processes

4.1.1 Motivation

  • Threads are very useful in modern programming whenever a process has multiple tasks to perform independently of the others.
  • This is particularly true when one of the tasks may block, and it is desired to allow the other tasks to proceed without blocking.
  • For example in a word processor, a background thread may check spelling and grammar while a foreground thread processes user input ( keystrokes ), while yet a third thread loads images from the hard drive, and a fourth does periodic automatic backups of the file being edited.
  • Another example is a web server - Multiple threads allow for multiple requests to be satisfied simultaneously, without having to service requests sequentially or to fork off separate processes for every incoming request. ( The latter is how this sort of thing was done before the concept of threads was developed. A daemon would listen at a port, fork off a child for every incoming request to be processed, and then go back to listening to the port. )


Figure 4.2 - Multithreaded server architecture

4.1.2 Benefits

  • There are four major categories of benefits to multi-threading:
    1. Responsiveness - One thread may provide rapid response while other threads are blocked or slowed down doing intensive calculations.
    2. Resource sharing - By default threads share common code, data, and other resources, which allows multiple tasks to be performed simultaneously in a single address space.
    3. Economy - Creating and managing threads ( and context switches between them ) is much faster than performing the same tasks for processes.
    4. Scalability, i.e. Utilization of multiprocessor architectures - A single threaded process can only run on one CPU, no matter how many may be available, whereas the execution of a multi-threaded application may be split amongst available processors. ( Note that single threaded processes can still benefit from multi-processor architectures when there are multiple processes contending for the CPU, i.e. when the load average is above some certain threshold. )

4.2 Multicore Programming

  • A recent trend in computer architecture is to produce chips with multiple cores, or CPUs on a single chip.
  • A multi-threaded application running on a traditional single-core chip would have to interleave the threads, as shown in Figure 4.3. On a multi-core chip, however, the threads could be spread across the available cores, allowing true parallel processing, as shown in Figure 4.4.


Figure 4.3 - Concurrent execution on a single-core system.


Figure 4.4 - Parallel execution on a multicore system

  • For operating systems, multi-core chips require new scheduling algorithms to make better use of the multiple cores available.
  • As multi-threading becomes more pervasive and more important ( thousands instead of tens of threads ), CPUs have been developed to support more simultaneous threads per core in hardware.

4.2.1 Programming Challenges ( New section, same content ? )

  • For application programmers, there are five areas where multi-core chips present new challenges:
    1. Identifying tasks - Examining applications to find activities that can be performed concurrently.
    2. Balance - Finding tasks to run concurrently that provide equal value. I.e. don't waste a thread on trivial tasks.
    3. Data splitting - To prevent the threads from interfering with one another.
    4. Data dependency - If one task is dependent upon the results of another, then the tasks need to be synchronized to assure access in the proper order.
    5. Testing and debugging - Inherently more difficult in parallel processing situations, as the race conditions become much more complex and difficult to identify.

4.2.2 Types of Parallelism ( new )

In theory there are two different ways to parallelize the workload:

  1. Data parallelism divides the data up amongst multiple cores ( threads ), and performs the same task on each subset of the data. For example dividing a large image up into pieces and performing the same digital image processing on each piece on different cores.
  2. Task parallelism divides the different tasks to be performed among the different cores and performs them simultaneously.

In practice no program is ever divided up solely by one or the other of these, but instead by some sort of hybrid combination.

4.3 Multithreading Models

  • There are two types of threads to be managed in a modern system: User threads and kernel threads.
  • User threads are supported above the kernel, without kernel support. These are the threads that application programmers would put into their programs.
  • Kernel threads are supported within the kernel of the OS itself. All modern OSes support kernel level threads, allowing the kernel to perform multiple simultaneous tasks and/or to service multiple kernel system calls simultaneously.
  • In a specific implementation, the user threads must be mapped to kernel threads, using one of the following strategies.

4.3.1 Many-To-One Model

  • In the many-to-one model, many user-level threads are all mapped onto a single kernel thread.
  • Thread management is handled by the thread library in user space, which is very efficient.
  • However, if a blocking system call is made, then the entire process blocks, even if the other user threads would otherwise be able to continue.
  • Because a single kernel thread can operate only on a single CPU, the many-to-one model does not allow individual processes to be split across multiple CPUs.
  • Green threads for Solaris and GNU Portable Threads implement the many-to-one model in the past, but few systems continue to do so today.


Figure 4.5 - Many-to-one model

4.3.2 One-To-One Model

  • The one-to-one model creates a separate kernel thread to handle each user thread.
  • One-to-one model overcomes the problems listed above involving blocking system calls and the splitting of processes across multiple CPUs.
  • However the overhead of managing the one-to-one model is more significant, involving more overhead and slowing down the system.
  • Most implementations of this model place a limit on how many threads can be created.
  • Linux and Windows from 95 to XP implement the one-to-one model for threads.


Figure 4.6 - One-to-one model

4.3.3 Many-To-Many Model

  • The many-to-many model multiplexes any number of user threads onto an equal or smaller number of kernel threads, combining the best features of the one-to-one and many-to-one models.
  • Users have no restrictions on the number of threads created.
  • Blocking kernel system calls do not block the entire process.
  • Processes can be split across multiple processors.
  • Individual processes may be allocated variable numbers of kernel threads, depending on the number of CPUs present and other factors.


Figure 4.7 - Many-to-many model

  • One popular variation of the many-to-many model is the two-tier model, which allows either many-to-many or one-to-one operation.
  • IRIX, HP-UX, and Tru64 UNIX use the two-tier model, as did Solaris prior to Solaris 9.


Figure 4.8 - Two-level model

4.4 Thread Libraries

  • Thread libraries provide programmers with an API for creating and managing threads.
  • Thread libraries may be implemented either in user space or in kernel space. The former involves API functions implemented solely within user space, with no kernel support. The latter involves system calls, and requires a kernel with thread library support.
  • There are three main thread libraries in use today:
    1. POSIX Pthreads - may be provided as either a user or kernel library, as an extension to the POSIX standard.
    2. Win32 threads - provided as a kernel-level library on Windows systems.
    3. Java threads - Since Java generally runs on a Java Virtual Machine, the implementation of threads is based upon whatever OS and hardware the JVM is running on, i.e. either Pthreads or Win32 threads depending on the system.
  • The following sections will demonstrate the use of threads in all three systems for calculating the sum of integers from 0 to N in a separate thread, and storing the result in a variable 'sum'.

4.4.1 Pthreads

  • The POSIX standard ( IEEE 1003.1c ) defines the specification for pThreads, not the implementation.
  • pThreads are available on Solaris, Linux, Mac OSX, Tru64, and via public domain shareware for Windows.
  • Global variables are shared amongst all threads.
  • One thread can wait for the others to rejoin before continuing.
  • pThreads begin execution in a specified function, in this example the runner( ) function:


Figure 4.9


New

4.4.2 Windows Threads

  • Similar to pThreads. Examine the code example to see the differences, which are mostly syntactic & nomenclature:


Figure 4.11

4.4.3 Java Threads

  • ALL Java programs use Threads - even 'common' single-threaded ones.
  • The creation of new Threads requires Objects that implement the Runnable Interface, which means they contain a method 'public void run( )' . Any descendant of the Thread class will naturally contain such a method. ( In practice the run( ) method must be overridden / provided for the thread to have any practical functionality. )
  • Creating a Thread Object does not start the thread running - To do that the program must call the Thread's 'start( )' method. Start( ) allocates and initializes memory for the Thread, and then calls the run( ) method. ( Programmers do not call run( ) directly. )
  • Because Java does not support global variables, Threads must be passed a reference to a shared Object in order to share data, in this example the 'Sum' Object.
  • Note that the JVM runs on top of a native OS, and that the JVM specification does not specify what model to use for mapping Java threads to kernel threads. This decision is JVM implementation dependant, and may be one-to-one, many-to-many, or many to one.. ( On a UNIX system the JVM normally uses PThreads and on a Windows system it normally uses windows threads. )


Figure 4.12

4.5 Implicit Threading ( Optional )

Shifts the burden of addressing the programming challenges outlined in section 4.2.1 above from the application programmer to the compiler and run-time libraries.

4.5.1 Thread Pools

  • Creating new threads every time one is needed and then deleting it when it is done can be inefficient, and can also lead to a very large ( unlimited ) number of threads being created.
  • An alternative solution is to create a number of threads when the process first starts, and put those threads into a thread pool.
    • Threads are allocated from the pool as needed, and returned to the pool when no longer needed.
    • When no threads are available in the pool, the process may have to wait until one becomes available.
  • The ( maximum ) number of threads available in a thread pool may be determined by adjustable parameters, possibly dynamically in response to changing system loads.
  • Win32 provides thread pools through the 'PoolFunction' function. Java also provides support for thread pools through the java.util.concurrent package, and Apple supports thread pools under the Grand Central Dispatch architecture..

4.5.2 OpenMP

Threads Of The Past Mac Os Catalina

  • OpenMP is a set of compiler directives available for C, C++, or FORTRAN programs that instruct the compiler to automatically generate parallel code where appropriate.
  • For example, the directive:

would cause the compiler to create as many threads as the machine has cores available, ( e.g. 4 on a quad-core machine ), and to run the parallel block of code, ( known as a parallel region ) on each of the threads.

  • Another sample directive is '#pragma omp parallel for', which causes the for loop immediately following it to be parallelized, dividing the iterations up amongst the available cores.

4.5.3 Grand Central Dispatch, GCD

  • GCD is an extension to C and C++ available on Apple's OSX and iOS operating systems to support parallelism.
  • Similar to OpenMP, users of GCD define blocks of code to be executed either serially or in parallel by placing a carat just before an opening curly brace, i.e. ^{ printf( 'I am a block.n' ); }
  • GCD schedules blocks by placing them on one of several dispatch queues.
    • Blocks placed on a serial queue are removed one by one. The next block cannot be removed for scheduling until the previous block has completed.
    • There are three concurrent queues, corresponding roughly to low, medium, or high priority. Blocks are also removed from these queues one by one, but several may be removed and dispatched without waiting for others to finish first, depending on the availability of threads.
  • Internally GCD manages a pool of POSIX threads which may fluctuate in size depending on load conditions.

4.5.4 Other Approaches

There are several other approaches available, including Microsoft's Threading Building Blocks ( TBB ) and other products, and Java's util.concurrent package.

4.6 Threading Issues

4.6.1 The fork( ) and exec( ) System Calls

  • Q: If one thread forks, is the entire process copied, or is the new process single-threaded?
  • A: System dependant.
  • A: If the new process execs right away, there is no need to copy all the other threads. If it doesn't, then the entire process should be copied.
  • A: Many versions of UNIX provide multiple versions of the fork call for this purpose.

4.6.2 Signal Handling

  • Q: When a multi-threaded process receives a signal, to what thread should that signal be delivered?
  • A: There are four major options:
    1. Deliver the signal to the thread to which the signal applies.
    2. Deliver the signal to every thread in the process.
    3. Deliver the signal to certain threads in the process.
    4. Assign a specific thread to receive all signals in a process.
  • The best choice may depend on which specific signal is involved.
  • UNIX allows individual threads to indicate which signals they are accepting and which they are ignoring. However the signal can only be delivered to one thread, which is generally the first thread that is accepting that particular signal.
  • UNIX provides two separate system calls, kill( pid, signal ) and pthread_kill( tid, signal ), for delivering signals to processes or specific threads respectively.
  • Windows does not support signals, but they can be emulated using Asynchronous Procedure Calls ( APCs ). APCs are delivered to specific threads, not processes.

4.6.3 Thread Cancellation

  • Threads that are no longer needed may be cancelled by another thread in one of two ways:
    1. Asynchronous Cancellation cancels the thread immediately.
    2. Deferred Cancellation sets a flag indicating the thread should cancel itself when it is convenient. It is then up to the cancelled thread to check this flag periodically and exit nicely when it sees the flag set.
  • ( Shared ) resource allocation and inter-thread data transfers can be problematic with asynchronous cancellation.

4.6.4 Thread-Local Storage ( was 4.4.5 Thread-Specific Data )

  • Most data is shared among threads, and this is one of the major benefits of using threads in the first place.
  • However sometimes threads need thread-specific data also.
  • Most major thread libraries ( pThreads, Win32, Java ) provide support for thread-specific data, known as thread-local storage or TLS. Note that this is more like static data than local variables,because it does not cease to exist when the function ends.

4.6.5 Scheduler Activations

  • Many implementations of threads provide a virtual processor as an interface between the user thread and the kernel thread, particularly for the many-to-many or two-tier models.
  • This virtual processor is known as a 'Lightweight Process', LWP.
    • There is a one-to-one correspondence between LWPs and kernel threads.
    • The number of kernel threads available, ( and hence the number of LWPs ) may change dynamically.
    • The application ( user level thread library ) maps user threads onto available LWPs.
    • kernel threads are scheduled onto the real processor(s) by the OS.
    • The kernel communicates to the user-level thread library when certain events occur ( such as a thread about to block ) via an upcall, which is handled in the thread library by an upcall handler. The upcall also provides a new LWP for the upcall handler to run on, which it can then use to reschedule the user thread that is about to become blocked. The OS will also issue upcalls when a thread becomes unblocked, so the thread library can make appropriate adjustments.
  • If the kernel thread blocks, then the LWP blocks, which blocks the user thread.
  • Ideally there should be at least as many LWPs available as there could be concurrently blocked kernel threads. Otherwise if all LWPs are blocked, then user threads will have to wait for one to become available.


Figure 4.13 - Lightweight process ( LWP )

4.7 Operating-System Examples ( Optional )

4.7.1 Windows XP Threads

Threads of the past mac os catalina
  • The Win32 API thread library supports the one-to-one thread model
  • Win32 also provides the fiber library, which supports the many-to-many model.
  • Win32 thread components include:
    • Thread ID
    • Registers
    • A user stack used in user mode, and a kernel stack used in kernel mode.
    • A private storage area used by various run-time libraries and dynamic link libraries ( DLLs ).
  • The key data structures for Windows threads are the ETHREAD ( executive thread block ), KTHREAD ( kernel thread block ), and the TEB ( thread environment block ). The ETHREAD and KTHREAD structures exist entirely within kernel space, and hence are only accessible by the kernel, whereas the TEB lies within user space, as illustrated in Figure 4.10:


Figure 4.14 - Data structures of a Windows thread

4.7.2 Linux Threads

  • Linux does not distinguish between processes and threads - It uses the more generic term 'tasks'.
  • The traditional fork( ) system call completely duplicates a process ( task ), as described earlier.
  • An alternative system call, clone( ) allows for varying degrees of sharing between the parent and child tasks, controlled by flags such as those shown in the following table:
flagMeaning
CLONE_FSFile-system information is shared
CLONE_VMThe same memory space is shared
CLONE_SIGHANDSignal handlers are shared
CLONE_FILESThe set of open files is shared
  • Calling clone( )with no flags set is equivalent to fork( ). Calling clone( ) with CLONE_FS, CLONE_VM, CLONE_SIGHAND, and CLONE_FILES is equivalent to creating a thread, as all of these data structures will be shared.
  • Linux implements this using a structure task_struct, which essentially provides a level of indirection to task resources. When the flags are not set, then the resources pointed to by the structure are copied, but if the flags are set, then only the pointers to the resources are copied, and hence the resources are shared. ( Think of a deep copy versus a shallow copy in OO programming. )
  • ( Removed from 9th edition ) Several distributions of Linux now support the NPTL ( Native POXIS Thread Library )
    • POSIX compliant.
    • Support for SMP ( symmetric multiprocessing ), NUMA ( non-uniform memory access ), and multicore processors.
    • Support for hundreds to thousands of threads.

4.8 Summary

So, you’ve decided to download an older version of Mac OS X. There are many reasons that could point you to this radical decision. To begin with, some of your apps may not be working properly (or simply crash) on newer operating systems. Also, you may have noticed your Mac’s performance went down right after the last update. Finally, if you want to run a parallel copy of Mac OS X on a virtual machine, you too will need a working installation file of an older Mac OS X. Further down we’ll explain where to get one and what problems you may face down the road.

A list of all Mac OS X versions

We’ll be repeatedly referring to these Apple OS versions below, so it’s good to know the basic macOS timeline.

Cheetah 10.0Puma 10.1Jaguar 10.2
Panther 10.3Tiger 10.4Leopard 10.5
Snow Leopard 10.6Lion 10.7Mountain Lion 10.8
Mavericks 10.9Yosemite 10.10El Capitan 10.11
Sierra 10.12High Sierra 10.13Mojave 10.14
Catalina 10.15

STEP 1. Prepare your Mac for installation

Given your Mac isn’t new and is filled with data, you will probably need enough free space on your Mac. This includes not just space for the OS itself but also space for other applications and your user data. One more argument is that the free space on your disk translates into virtual memory so your apps have “fuel” to operate on. The chart below tells you how much free space is needed.

Note, that it is recommended that you install OS on a clean drive. Next, you will need enough disk space available, for example, to create Recovery Partition. Here are some ideas to free up space on your drive:

  • Uninstall large unused apps
  • Empty Trash Bin and Downloads
  • Locate the biggest files on your computer:

Go to Finder > All My Files > Arrange by size
Then you can move your space hoggers onto an external drive or a cloud storage.
If you aren’t comfortable with cleaning the Mac manually, there are some nice automatic “room cleaners”. Our favorite is CleanMyMac as it’s most simple to use of all. It deletes system junk, old broken apps, and the rest of hidden junk on your drive.

Download CleanMyMac for OS 10.4 - 10.8 (free version)

Download CleanMyMac for OS 10.9 (free version)

Download CleanMyMac for OS 10.10 - 10.14 (free version)

STEP 2. Get a copy of Mac OS X download

Normally, it is assumed that updating OS is a one-way road. That’s why going back to a past Apple OS version is problematic. The main challenge is to download the OS installation file itself, because your Mac may already be running a newer version. If you succeed in downloading the OS installation, your next step is to create a bootable USB or DVD and then reinstall the OS on your computer.

How to download older Mac OS X versions via the App Store


If you once had purchased an old version of Mac OS X from the App Store, open it and go to the Purchased tab. There you’ll find all the installers you can download. However, it doesn’t always work that way. The purchased section lists only those operating systems that you had downloaded in the past. But here is the path to check it:

  1. Click the App Store icon.
  2. Click Purchases in the top menu.
  3. Scroll down to find the preferred OS X version.
  4. Click Download.

This method allows you to download Mavericks and Yosemite by logging with your Apple ID — only if you previously downloaded them from the Mac App Store.

Without App Store: Download Mac OS version as Apple Developer

If you are signed with an Apple Developer account, you can get access to products that are no longer listed on the App Store. If you desperately need a lower OS X version build, consider creating a new Developer account among other options. The membership cost is $99/year and provides a bunch of perks unavailable to ordinary users.

Nevertheless, keep in mind that if you visit developer.apple.com/downloads, you can only find 10.3-10.6 OS X operating systems there. Newer versions are not available because starting Mac OS X Snow Leopard 10.7, the App Store has become the only source of updating Apple OS versions.

Purchase an older version of Mac operating system

You can purchase a boxed or email version of past Mac OS X directly from Apple. Both will cost you around $20. For the reason of being rather antiquated, Snow Leopard and earlier Apple versions can only be installed from DVD.

Buy a boxed edition of Snow Leopard 10.6
Get an email copy of Lion 10.7
Get an email copy of Mountain Lion 10.8

The email edition comes with a special download code you can use for the Mac App Store. Note, that to install the Lion or Mountain Lion, your Mac needs to be running Snow Leopard so you can install the newer OS on top of it.

How to get macOS El Capitan download

If you are wondering if you can run El Capitan on an older Mac, rejoice as it’s possible too. But before your Mac can run El Capitan it has to be updated to OS X 10.6.8. So, here are main steps you should take:

1. Install Snow Leopard from install DVD.
2. Update to 10.6.8 using Software Update.
3. Download El Capitan here.

“I can’t download an old version of Mac OS X”

If you have a newer Mac, there is no physical option to install Mac OS versions older than your current Mac model. For instance, if your MacBook was released in 2014, don’t expect it to run any OS released prior of that time, because older Apple OS versions simply do not include hardware drivers for your Mac.

But as it often happens, workarounds are possible. There is still a chance to download the installation file if you have an access to a Mac (or virtual machine) running that operating system. For example, to get an installer for Lion, you may ask a friend who has Lion-operated Mac or, once again, set up a virtual machine running Lion. Then you will need to prepare an external drive to download the installation file using OS X Utilities.

After you’ve completed the download, the installer should launch automatically, but you can click Cancel and copy the file you need. Below is the detailed instruction how to do it.

STEP 3. Install older OS X onto an external drive

The following method allows you to download Mac OS X Lion, Mountain Lion, and Mavericks.

  1. Start your Mac holding down Command + R.
  2. Prepare a clean external drive (at least 10 GB of storage).
  3. Within OS X Utilities, choose Reinstall OS X.
  4. Select external drive as a source.
  5. Enter your Apple ID.

Now the OS should start downloading automatically onto the external drive. After the download is complete, your Mac will prompt you to do a restart, but at this point, you should completely shut it down. Now that the installation file is “captured” onto your external drive, you can reinstall the OS, this time running the file on your Mac.

  1. Boot your Mac from your standard drive.
  2. Connect the external drive.
  3. Go to external drive > OS X Install Data.

Locate InstallESD.dmg disk image file — this is the file you need to reinstall Lion OS X. The same steps are valid for Mountain Lion and Mavericks.

How to downgrade a Mac running later macOS versions

If your Mac runs macOS Sierra 10.12 or macOS High Sierra 10.13, it is possible to revert it to the previous system if you are not satisfied with the experience. You can do it either with Time Machine or by creating a bootable USB or external drive.
Instruction to downgrade from macOS Sierra

Instruction to downgrade from macOS High Sierra

Instruction to downgrade from macOS Mojave

Instruction to downgrade from macOS Catalina

Before you do it, the best advice is to back your Mac up so your most important files stay intact. In addition to that, it makes sense to clean up your Mac from old system junk files and application leftovers. The easiest way to do it is to run CleanMyMac X on your machine (download it for free here).

Threads Of The Past Mac Os X

Visit your local Apple Store to download older OS X version

Threads Of The Past Mac Os Update

If none of the options to get older OS X worked, pay a visit to nearest local Apple Store. They should have image installations going back to OS Leopard and earlier. You can also ask their assistance to create a bootable USB drive with the installation file. So here you are. We hope this article has helped you to download an old version of Mac OS X. Below are a few more links you may find interesting.