Reference documentation for kernel side function APIs, specifies a wide variety of pre-conditions and post-conditions.
A pre-condition is something that must be true before using the function.
A post-condition is something that is true on return from the function.
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.
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.
Must be called under an XTRAP harness or calling thread must not be in a critical section
The various parameters must be valid. The PIL or PSL will fault the kernel if not
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.
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.
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.
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().
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().
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.
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.
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.
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.
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.
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.
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.
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.
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:
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().
The described function accesses an object whose internal data needs to be protected by the specified fast mutex.
The operations of:
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().
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:
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.
A post condition describes what is true on return from a kernel API function.
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.
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.
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.
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.
This post-condition states that interrupts are enabled on return from the described function.
See the pre-condition Interrupts must be enabled
This post-condition states that interrupts are disabled on return from the described function.
See the pre-condition Interrupts must be disabled
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.
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().
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.