diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-63456B20-3A61-554A-BBA4-C23B176E39A8.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-63456B20-3A61-554A-BBA4-C23B176E39A8.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,433 @@ + + + + + +Pre-Conditions +and Post-Conditions for Kernel APIsReference documentation for kernel side function APIs, specifies +a wide variety of pre-conditions and post-conditions. + +

Such conditions are expressed using a standard phrase, wherever possible, +and this section explains what those conditions mean.

+

Where more than one pre-condition is stated for a given function, then +you can assume that all pre-conditions apply. In this sense, there is an implied +AND relation between conditions. For example, in the description of the function DObject::AppendFullName(), +the following pre-conditions apply:

+No fast mutex can be held. +Call in a thread context. +

Both conditions must be true before calling the functions.

+

There are exceptions to this rule, where a precondition applies only if +some other factor is true. For example, in the description of the function DObject::TraceAppendName(), +you will find the following pre-conditions:

+Call either in a thread or an IDFC context, if aLock=TRUE +Call in any context, if aLock=FALSE. +

Clearly, only one pre-condition will apply, depending on the supplied value +of the aLock argument.

+

A few conditions are self-explanatory, and these are not included in these +lists.

+

NOTE that some familiarity with kernel side programming is assumed.

+ +
Pre-conditions

This +describes the meaning of each precondition, and tries to provide insight as +to why it needs to be satisfied, and explains what you need to do to ensure +that the preconditions are met.

    +
  • Calling thread must be in a critical section

  • +
  • Calling thread must not be in a critical section

  • +
  • Calling thread can either be in a critical section or not

  • +
  • No fast mutex can be held

  • +
  • Kernel must be locked

  • +
  • Kernel must be unlocked

  • +
  • Kernel can be locked or unlocked

  • +
  • Kernel must be locked, with lock count 1

  • +
  • Interrupts must be enabled

  • +
  • Interrupts must be disabled

  • +
  • Interrupts can either be enabled or disabled

  • +
  • System lock must be held

  • +
  • System lock must not be held

  • +
  • Call in a thread context

  • +
  • Call in an IDFC contex

  • +
  • Call either in a thread or an IDFC context

  • +
  • Call in any context

  • +
  • Do not call from an ISR

  • +
  • The calling thread must own the semaphore

  • +
  • The calling thread must not be explicitly suspended

  • +
  • The calling thread must hold the mutex

  • +
  • Call only from ISR, IDFC or thread with the kernel locked

  • +
  • Call only from IDFC or thread with the kernel locked

  • +
  • Do not call from thread with the kernel unlocked

  • +
  • Do not call from ISR or thread with the kernel unlocked

  • +
  • Thread must not already be exiting

  • +
  • Property has not been opened

  • +
  • Property has been opened

  • +
  • Must be called under an XTRAP harness or calling thread must not be in a +critical section

  • +
  • DObject::Lock fast mutex held

  • +
  • DCodeSeg::CodeSegLock mutex held

  • +
  • Any kind of lock can be held

  • +
  • Call only from Init1() in base port

  • +
  • The various parameters must be valid. The PIL or PSL will fault the kernel +if not

  • +
  • The request is not being transferred or pending

  • +
  • Wait on TimerMutex before calling this

  • +
  • Message must be in ACCEPTED state

  • +
  • Queue must not be in asynchronous receive mode

  • +
  • Container mutex must be held

  • +
  • Thread container mutex must be held

  • +
  • Process container mutex must be held

  • +

Calling thread must be in +a critical section

Critical sections are sections of code that +leave the kernel in a compromised state if they cannot complete. A thread +enters a critical section by calling NKern::ThreadEnterCS() and +leaves it by calling NKern::ThreadLeaveCS().

While +in a critical section, the thread cannot be suspended or killed. These actions +are deferred until the end of the critical section. If a thread takes an exception +while inside a critical section, this is treated as fatal to the system, and +cause a Kern::Fault().

The described function must +be in a critical section when called.

Calling thread must not +be in a critical section

Critical sections are sections of code +that leave the kernel in a compromised state if they cannot complete. A thread +enters a critical section by calling NKern::ThreadEnterCS() and +leaves it by calling NKern::ThreadLeaveCS().

While +in a critical section, the thread cannot be suspended or killed. These actions +are deferred until the end of the critical section. If a thread takes an exception +while inside a critical section, this is treated as fatal to the system, and +cause a Kern::Fault().

There are some functions winthin +the system that must NOT be in a critical section when called. This +applies to the described functions.

Calling thread can either +be in a critical section or not

Critical sections are sections +of code that leave the kernel in a compromised state if they cannot complete. +A thread enters a critical section by calling NKern::ThreadEnterCS() and +leaves it by calling NKern::ThreadLeaveCS().

While +in a critical section, the thread cannot be suspended or killed. These actions +are deferred until the end of the critical section. If a thread takes an exception +while inside a critical section, this is treated as fatal to the system, and +cause a Kern::Fault().

When this pre-condition applies +to the described function, it means that it does not matter whether the code +is in a critical section or not.

No fast mutex can be held

A +thread can hold no more than one fast mutex at any given time. The described +function uses a fast mutex, which means that on entry to the function, the +calling thread must not hold another one.

Kernel must be locked

Many +kernel side functions run with interrupts enabled, including code that manipulates +global structures, such as the thread ready list. To prevent such code from +being reentered and potentially corrupting the structure concerned, a lock +known as the kernel lock (sometimes referred to as the preemption lock) is +used.

Sections of code that need to be protected against rescheduling +call NKern::Lock(). Interrupt Service Routines (ISRs) can +still run but no other thread (or IDFC) can run until the kernel is unlocked +by a call to NKern::Unlock().

The pre-condition +means that the kernel lock must be set before calling the described function.

Kernel must be unlocked

Many +kernel side functions run with interrupts enabled, including code that manipulates +global structures, such as the thread ready list. To prevent such code from +being reentered and potentially corrupting the structure concerned, a lock +known as the kernel lock (sometimes referred to as the preemption lock) is +used.

Sections of code that need to be protected against rescheduling +call NKern::Lock(). Interrupt Service Routines (ISRs) can +still run but no other thread (or IDFC) can run until the kernel is unlocked +by a call to NKern::Unlock().

The pre-condition +means that the kernel lock must NOT be set when the described function +is called.

Kernel can be locked or +unlocked

Many kernel side functions run with interrupts enabled, +including code that manipulates global structures, such as the thread ready +list. To prevent such code from being reentered and potentially corrupting +the structure concerned, a lock known as the kernel lock (sometimes referred +to as the preemption lock) is used.

Sections of code that need to +be protected against rescheduling call NKern::Lock(). Interrupt +Service Routines (ISRs) can still run but no other thread (or IDFC) can run +until the kernel is unlocked by a call to NKern::Unlock().

The +pre-condition means that it does not matter whether the kernel lock is set +or unset when the described function is called.

Kernel must be locked, with +lock count 1

Many kernel side functions run with interrupts enabled, +including code that manipulates global structures, such as the thread ready +list. To prevent such code from being reentered and potentially corrupting +the structure concerned, a lock known as the kernel lock (sometimes referred +to as the preemption lock) is used.

Sections of code that need to +be protected against rescheduling call NKern::Lock(). Interrupt +Service Routines (ISRs) can still run but no other thread (or IDFC) can run +until the kernel is unlocked by a call to NKern::Unlock().

In +addition, calls to NKern::Lock() and NKern::Unlock() are +counted. The count value is zero when the kernel is unlocked; a call to NKern::Lock() adds +one to the count value, and a call to NKern::Unlock() subtracts +one from the count value.

The pre-condition means that there must +be exactly one call to Kern::Lock() that has not yet had +a matching call to Kern::Unlock().

See also NFastMutex::Wait().

Interrupts must be enabled

This +pre-condition states that interrupts must be enabled before calling the described +function.

Possible reasons why interrupts may need to be enabled include:

    +
  • the function needs interrupts +to occur; for example, it may wait for timer ticks.

  • +
  • the function may take +a long or potentially unbounded time to run, so interrupts need to be enabled +to guarantee bounded interrupt latency.

  • +

See also the function NKern::RestoreInterrupts() and +the associated function NKern::DisableInterrupts().

Interrupts must be disabled

This +pre-condition states that interrupts must be disabled before calling the described +function.

See also the function NKern::DisableInterrupts() and +the associated function NKern::RestoreInterrupts().

Interrupts can either be +enabled or disabled

This pre-condition states that it does not +matter whether interrupts are enabled or disabled before calling the described +function.

System lock must be held

The +system lock is a specific fast mutex that only provides exclusion against +other threads acquiring the same fast mutex. Setting, and acquiring the system +lock means that a thread enters an implied critical section.

The major +items protected by the system lock are:

    +
  • DThread member +data related to thread priority and status.

  • +
  • the consistency of the +memory map; on the kernel side, the state of user side memory or the mapping +of a process is not guaranteed unless (a) you are a thread belonging to the +process that owns the memory or (b) you hold the system lock.

  • +
  • the lifetime of DObject type +objects and references to them, including handle translation in Exec dispatch.

  • +

Note that the system lock is different from the kernel lock; the +kernel lock protects against any rescheduling. When the system lock is set, +the calling thread can still be pre-empted, even in the locked section.

The +system lock is set by a call to NKern::LockSystem().

The +pre-condition means that the system lock must be set before calling the described +function.

System lock must not be +held

See the pre-condition System +lock must be held for a brief description of the system lock.

The +system lock is unset by a call to NKern::UnlockSystem().

The +pre-condition means that the system lock must not be set before calling the +described function.

Call in a thread context

This +pre-condition means that the described function must be called directly, or +indirectly, from a DFC or a thread. The thread can be a user thread or a kernel +thread.

Call in an IDFC contex

This +pre-condition means that the described function must be called directly, or +indirectly, from an IDFC.

Note that when calling a function from an +IDFC:

    +
  • the kernel is locked, +so pre-emption is disabled

  • +
  • user memory cannot be +accessed

  • +
  • the function cannot +block or wait.

  • +

Call either in a thread +or an IDFC context

This pre-condition means that the described +function can be called directly, or indirectly, from an IDFC, a DFC or a thread. +The thread can be a user thread or a kernel thread.

Note that when +calling a function from an IDFC:

    +
  • the kernel is locked, +so pre-emption is disabled

  • +
  • user memory cannot be +accessed

  • +
  • the function cannot +block or wait.

  • +

Call in any context

This +pre-condition means that the described function can be called directly, or +indirectly, from an IDFC, a DFC or a thread, or it can be called from an Interrupt +Service Routine (ISR).

A thread can be a user thread or a kernel thread.

Note +that when calling a function from an IDFC:

    +
  • the kernel is locked, +so pre-emption is disabled

  • +
  • user memory cannot be +accessed

  • +
  • the function cannot +block or wait.

  • +

Do not call from an ISR

This +pre-condition means that the described function must not be called from an +Interrupt Service Routine (ISR).

Note that ISRs have the following +characteristics:

    +
  • they have an unknown +context

  • +
  • they must not allocate +or free memory

  • +
  • they cannot access user +memory

  • +
  • they must not call functions +that interfere with critical sections of code.

  • +

The calling thread must +own the semaphore

A semaphore can be waited on only by the thread +that owns it. This precondition is needed when the described function calls +a semaphore wait function.

The calling thread must +not be explicitly suspended

This refers to nanokernel threads, +not Symbian platform threads. The described function must not be used if the +thread is in the suspended state. One of the possible reasons for this is +that the described function does not check the thread's suspend count.

A +thread may be created suspended, or the thread may be put into a suspended +state using NThreadBase::Suspend(). If you don't know whether +or not the thread is suspended, use NThreadBase::CheckSuspendThenReady().

See +also NThreadBase::Resume() and NThreadBase::ForceResume().

Note +that these functions are for use only in an RTOS personality layer.

The calling thread must +hold the mutex

The calling thread has waited for a mutex and acquired +it. This precondition is needed when the thread is about to release the mutex, +ie call one of the Signal() functions.

Call only from ISR, IDFC +or thread with the kernel locked

See the pre-condition Kernel must be locked.

Call only from IDFC or thread +with the kernel locked

See the pre-condition Kernel must be locked.

Do not call from thread +with the kernel unlocked

See the pre-condition Kernel must be unlocked.

Do not call from ISR or +thread with the kernel unlocked

See the pre-condition Kernel must be unlocked.

Thread must not already +be exiting

The pre-condition means that the described function +should not be called after the thread has been killed.

In EKA2, threads +do not die immediately, they are placed on a queue to be deleted later.

Functions +with this pre-condition are not likely to used in a device driver.

Property has not been opened

A +property is a single value used by “Publish and Subscribe”. Each property +must be opened before it can be used. To open a property, use either RPropertyRef::Attach() or RPropertyRef::Open(). Once opened, the property cannot be opened again.

The pre-condition +means that the property must NOT already be open when the described +function is called.

Property has been opened

A +property is a single value used by “Publish and Subscribe”. Each property +must be opened before it can be used. To open a property, use either RPropertyRef::Attach() or RPropertyRef::Open(). Once opened, the property cannot be opened again.

The pre-condition +means that the property must already be open before calling the described +function.

Must be called under an +XTRAP harness or calling thread must not be in a critical section

Each +Symbian platform thread can be associated with a kernel-side +exception handler, set using XTRAP(); for example, to detect bad memory accesses.

The +described function can legitimately cause an exception, and the pre-condition +means that

either:

    +
  • the described function +should be called inside an XTRAP() harness to catch the exception

  • +

or

    +
  • the thread must not +be in a critical section, because exceptions are not allowed inside them. +If a thread takes an exception while inside a critical section, this is treated +as fatal to the system, and causes a Kern::Fault().

  • +

DObject::Lock fast mutex +held

The described function accesses an object whose internal +data needs to be protected by the specified fast mutex.

The operations +of:

    +
  • obtaining an object’s +name

  • +
  • setting an object's +name

  • +
  • setting an object's +owner

  • +

are all protected by the global fast mutex, DObject::Lock. +This is done to avoid inconsistent results caused by, for example, one thread +renaming an object while another is reading its name or full name.

Setting +the owner is protected as the owner's name is part of the object's full name.

DCodeSeg::CodeSegLock mutex +held

The DCodeSeg::CodeSegLock mutex protects +the global code graph from simultaneous accesses. Wait on this mutex before +calling the described function, e.g. by calling DCodeSeg::Wait().

Any kind of lock can be +held

The described function can be called with any kind of lock.

Call only from Init1() in +base port

The pre-condition means that the described function +can only be called during the first phase of kernel initialisation, i.e. during +execution of the Base Port implementation of Asic::Init1(). +See the Board Support +Packages Quick Start.

This condition may apply because the +described function:

    +
  • must be called before +any context switch

  • +
  • must be called before +the MMU is turned on.

  • +

The various parameters must +be valid. The PIL or PSL will fault the kernel if not

This pre-condition +refers to a DMA request.

The parameters used when calling the described +function must be as specified. If they are not, the platform independent layer +or the platform specific layer cannot recover and will cause the kernel to +fault, i.e. the device will reset.

The request is not being +transferred or pending

This pre-condition refers to a DMA request.

The +described function must not be called if a DMA request has already been set +up, or is in progress. A possible reason for this is that the described function +resets parameters that have been already setup.

Wait on TimerMutex before +calling this

The TimerMutex mutex protects the +timer queues. Wait and signal operations on the timer mutex are accomplished +with the static functions TTickQ::Wait() and TTickQ::Signal(). +This precondition is necessary when the described function manipulates the +timer queue.

Message must be in ACCEPTED +state

This pre-condition indicates that the message has been read +by the receiving thread. It is not attached to a message queue but is currently +in use by the receiving thread.

Queue must not be in asynchronous +receive mode

This pre-condition refers to kernel side message +queues. A kernel thread can receive messages:

    +
  • asynchronously by calling TMessageQue::Receive()

  • +
  • by polling, by calling MessageQue::Poll()

  • +

A possible reason for this precondition is that the queue is about +to be polled.

The queue may be polled either:

    +
  • before the first Receive() is +issued

  • +
  • while processing a message +but before Receive() is called again

  • +

Container mutex must be +held / Thread container mutex must be held / Process container mutex must +be held

Each of the containers is protected by a mutex.

The +pre-condition means that the calling thread must acquire the relevant mutex +before calling the described function. Object containers are DObjectCon types, +and the relevant mutexes are acquired and freed by calling Wait() and Signal() on +the container object.

+
Post-conditions

A +post condition describes what is true on return from a kernel API function.

    +
  • Calling thread is in a critical section

  • +
  • Calling thread is not in a critical section

  • +
  • No fast mutex is held

  • +
  • Kernel is locked

  • +
  • Kernel is unlocked

  • +
  • Kernel is locked, with lock count 1

  • +
  • Interrupts are enabled

  • +
  • Interrupts are disabled

  • +
  • System lock is held

  • +
  • The calling thread holds the mutex

  • +
  • Container mutex is held

  • +
  • Thread container mutex is held

  • +
  • Process container mutex is held

  • +
  • DCodeSeg::CodeSegLock mutex held

  • +

Calling thread is in a critical +section

The code is in a critical section on return from the function.

See +also the pre-condition: Calling +thread must be in a critical section.

Calling thread is not in +a critical section

The code is NOT in a critical section +on return from the function.

See also the pre-condition: Calling thread must not be in a critical section.

No fast mutex is held

A +thread can hold no more than one fast mutex at any given time. A fast mutex +is NOT held on exit from the function.

Kernel is locked

The +post-condition means that, on exit from the described function, the kernel +lock is on. The described function might have explicitly set the kernel lock +or, more commonly, the lock was set before entry to the described function, +and has not been unset by that function.

See also the pre-condition Kernel +must be locked.

Kernel is unlocked

The +kernel is NOT locked on exit from the described function. The described +function might have explicitly unset the kernel lock or, more commonly, the +lock was not set before entry to the described function, and has not been +set by that function.

See also the pre-condition Kernel must be unlocked.

Kernel is locked, with lock +count 1

See the pre-condition Kernel +must be locked, with lock count 1.

Interrupts are enabled

This +post-condition states that interrupts are enabled on return from the described +function.

See the pre-condition Interrupts +must be enabled

Interrupts are disabled

This +post-condition states that interrupts are disabled on return from the described +function.

See the pre-condition Interrupts +must be disabled

System lock is held

This +post-condition states that the system lock is held on return from the described +function.

The system lock is a specific fast mutex that only provides +exclusion against other threads acquiring the same fast mutex. Setting, and +acquiring the system lock means that a thread enters an implied critical section.

The +major items protected by the system lock are:

    +
  • DThread member +data related to thread priority and status.

  • +
  • the consistency of the +memory map; on the kernel side, the state of user side memory or the mapping +of a process is not guaranteed unless (a) you are a thread belonging to the +process that owns the memory or (b) you hold the system lock.

  • +
  • the lifetime of DObject type +objects and references to them, including handle translation in Exec dispatch.

  • +

System lock is different from the kernel lock; the kernel +lock protects against any rescheduling. When the system lock is set, the calling +thread can still be pre-empted, even in the locked section.

The +system lock is set by a call to NKern::LockSystem(), and +unset by call to NKern::UnlockSystem().

The calling thread holds +the mutex

The calling thread has waited for a mutex and acquired +it. On return from the described function, the thread still holds the mutex.

See +also the pre-condition The +calling thread must hold the mutex.

Container mutex is held +/ Thread container mutex is held / Process container mutex is held

Each +of the containers is protected by a mutex.

The post-condition means +that the calling thread has the relevant mutex on return from the described +function. This is most likely because the mutex was acquired before entering +the described function.

Object containers are DObjectCon types, +and the relevant mutexes are acquired and freed by calling Wait() and Signal() on +the container object.

DCodeSeg::CodeSegLock mutex +held

The DCodeSeg::CodeSegLock mutex protects +the global code graph from simultaneous accesses.

This post condition +means that the mutex is held on exit. The most common situation is that the +mutex was acquired before entry to the described function. Relinquish the +mutex by calling DCodeSeg::Signal().

+
\ No newline at end of file