http://www.aros.orgAROS-ExecAROS-Exec ArchivesPower2People

Home

English

Česky

Deutsch

Ελληυικά

Français

Italiano

Nederlands

Polski

Português

Русский

Español

Suomi

Svenska


Neues

Archiv

Einleitung

Status
Screenshots
Portierungen
Lizens

Download


Dokumentation

Benutzer
Installation
Benutzung
Shell
Anwendungen
FAQ
Entwickler
Mitwirken
Roadmap
Fehlermeldung
Arbeiten mit Subversion
Kompilierung
Anwendungs Entwicklungs Handbuch
Zune Anwendungs Entwicklungs Handbuch
System Entwicklungs Handbuch
Debugging Handbuch
Referenz
Spezifikationen
Benutzeroberflächen Richtlinien
Dokumentierung
Portierung
Übersetzung
Zusammenfassungen
Links

Kontakt

Mailinglisten
IRC-Kanäle

Danksagung

Acknowledgements


Bilder

Entwickler
Entwicklertreffen

Sponsoren

Verlinkung

Links

Get AROS Research Operating System at SourceForge.net. Fast, secure and Free Open Source software downloads

The exec microkernel

Bemerkung

This document is currently only a draft and will most likely change before it is accepted as an official specification. It might also be deprecated if a better aproach has been found and might not correspond precisely with the current implementation.

This document describes the inner workings of exec.library. It's not for normal application programmers but for people who are interested in such a thing. Most of the things described herein are system private - they may or may not be true for future system version.

Exec is a shared library giving the ability for multitasking including communication between tasks, memory management, shared libraries and device I/O. Large parts of this library are formed by a set of functions that are called on the users schedule just like any normal C function is (though they do things you'd usually expect in a kernel). These functions make up the library part of exec which is built on a smaller set of functions which form the core of exec (you may call them the real kernel if you like). This machine dependant core serves things like supervisor mode, traps, interrupts, task exceptions and context switching routines.

The core of exec in short:

ULONG Supervisor(ULONG (*)());
Calls a user function in supervisor mode.
APTR tc_TrapData; and APTR tc_TrapCode;
User settable trap vector.
IntVects[i]
The different interrupt vectors.
void Disable(void);
Disable interrupts.
void Enable(void);
Enable interrupts.
BYTE IDNestCnt;
-1 if interrupts are allowed.
APTR PrepareContext(APTR);
Prepare a new stack to hold a context.
void Switch(void);
Do a task switch.
AttnFlags & 0x8000
Delayed dispatch flag.
AttnFlags & 0x80
Delayed switch flag.
tc_Flags & TF_SWITCH
tc_Switch is active.
void (*tc_Switch)();
Vector to be called before task loses CPU.
tc_Flags & TF_LAUNCH
tc_Launch is active.
void (*tc_Launch)();
Vector to be called before task gets CPU.
UBYTE tc_State;
Where the actual task structure is sorted in.
struct Task *ThisTask;
Pointer to actual task structure.
struct List TaskReady;
Sorted list of tasks waiting for CPU.
tc_Flags & TF_EXCEPT
Raise a task exception for this task at the next context switch.
void Exception(void);
Is called to handle the task exception.

The most important part are the context switching routines. The context of every task is stored on the task's user stack. The stackpointer is stored in the task structure. Context switches are raised by moving the current task to one of the two task lists (must be done with interrupts Disable()d) and then calling Switch(). However if this happens inside an interrupt (which is allowed and quite useful) the user context is unavailable. Therefore Switch() checks if it was called from user mode and sets the delayed dispatch flag if not. This flag tells the interrupt primitives to do a context switch (by calling Dispatch()) before falling down to user mode. When called from user mode Switch() calls Dispatch() directly. Dispatch() is the function which does the real work, i.e. it replaces the current task with the first task in the ready list. If the TF_EXCEPT flag for the new task is set Dispatch() raises a task exception by calling the Exception() vector of exec with interrupts Disable()d. tc_Switch and tc_Launch are also handled by Dispatch().

The usual way to do a context switch is as follows:

if(I_need_a_task_switch)
{
  /* The task lists must be protected with a Disable() */
  Disable();
  /* check if taskswitches are allowed */
  if(SysBase->TDNestCnt<0&&SysBase->IDNestCnt<=0)
  {
    /* Check if there is already a pending task switch (this check can
       be skipped if I can guarantee to be in user mode). */
    if(SysBase->ThisTask->tc_State==TS_RUN)
    {
      /* No. Move the current task away */
      Enqueue(new_list,SysBase->ThisTask);
      SysBase->ThisTask->tc_State=new_state;
      /* And do the switch */
      Switch();
    }
  }else
    /* Memorize taskswitch for a later Enable() or Permit(). */
    SysBase->AttnFlags|=0x80;
  Enable();
}

Interrupts and traps are delivered with direct function calls. The different interrupt levels call different interrupt vectors (stored in IntVects[i]). Traps are raised by calling the tc_TrapCode vector of the current task (usually this ends up in an Alert() - the exec equivalent of a kernel panic). Interrupts may be disabled completely (by calling Disable(), Enable() enables them again, Disable() calls may be nested) but only for a short time.


Copyright © 1995-2009, The AROS Development Team. All rights reserved.
Amiga®, AmigaOS®, Workbench und Intuition sind eingetragene Warenzeichen von Amiga Inc. Alle anderen Warenzeichen gehören dem jeweiligen Besitzer.