summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/src')
-rw-r--r--cpukit/score/src/Unlimited.txt364
-rw-r--r--cpukit/score/src/apiext.c113
-rw-r--r--cpukit/score/src/apimutex.c37
-rw-r--r--cpukit/score/src/apimutexallocate.c39
-rw-r--r--cpukit/score/src/apimutexlock.c34
-rw-r--r--cpukit/score/src/apimutexunlock.c30
-rw-r--r--cpukit/score/src/chain.c61
-rw-r--r--cpukit/score/src/chainappend.c46
-rw-r--r--cpukit/score/src/chainappendempty.c44
-rw-r--r--cpukit/score/src/chainextract.c44
-rw-r--r--cpukit/score/src/chainget.c51
-rw-r--r--cpukit/score/src/chaingetempty.c44
-rw-r--r--cpukit/score/src/chaininsert.c47
-rw-r--r--cpukit/score/src/chainprependempty.c44
-rw-r--r--cpukit/score/src/corebarrier.c57
-rw-r--r--cpukit/score/src/corebarrierrelease.c70
-rw-r--r--cpukit/score/src/corebarrierwait.c78
-rw-r--r--cpukit/score/src/coremsg.c120
-rw-r--r--cpukit/score/src/coremsgbroadcast.c116
-rw-r--r--cpukit/score/src/coremsgclose.c77
-rw-r--r--cpukit/score/src/coremsgflush.c55
-rw-r--r--cpukit/score/src/coremsgflushsupp.c106
-rw-r--r--cpukit/score/src/coremsgflushwait.c72
-rw-r--r--cpukit/score/src/coremsginsert.c133
-rw-r--r--cpukit/score/src/coremsgseize.c157
-rw-r--r--cpukit/score/src/coremsgsubmit.c180
-rw-r--r--cpukit/score/src/coremutex.c94
-rw-r--r--cpukit/score/src/coremutexflush.c55
-rw-r--r--cpukit/score/src/coremutexseize.c78
-rw-r--r--cpukit/score/src/coremutexseizeintr.c33
-rw-r--r--cpukit/score/src/coremutexsurrender.c231
-rw-r--r--cpukit/score/src/corerwlock.c61
-rw-r--r--cpukit/score/src/corerwlockobtainread.c108
-rw-r--r--cpukit/score/src/corerwlockobtainwrite.c99
-rw-r--r--cpukit/score/src/corerwlockrelease.c106
-rw-r--r--cpukit/score/src/corerwlocktimeout.c55
-rw-r--r--cpukit/score/src/coresem.c63
-rw-r--r--cpukit/score/src/coresemflush.c58
-rw-r--r--cpukit/score/src/coresemseize.c88
-rw-r--r--cpukit/score/src/coresemsurrender.c76
-rw-r--r--cpukit/score/src/corespinlock.c53
-rw-r--r--cpukit/score/src/corespinlockrelease.c72
-rw-r--r--cpukit/score/src/corespinlockwait.c114
-rw-r--r--cpukit/score/src/coretod.c47
-rw-r--r--cpukit/score/src/coretodget.c56
-rw-r--r--cpukit/score/src/coretodgetuptime.c56
-rw-r--r--cpukit/score/src/coretodgetuptimetimespec.c44
-rw-r--r--cpukit/score/src/coretodmsecstoticks.c25
-rw-r--r--cpukit/score/src/coretodset.c62
-rw-r--r--cpukit/score/src/coretodtickle.c60
-rw-r--r--cpukit/score/src/coretodtickspersec.c24
-rw-r--r--cpukit/score/src/coretodusectoticks.c25
-rw-r--r--cpukit/score/src/heap.c488
-rw-r--r--cpukit/score/src/heapallocate.c280
-rw-r--r--cpukit/score/src/heapextend.c243
-rw-r--r--cpukit/score/src/heapfree.c215
-rw-r--r--cpukit/score/src/heapgetfreeinfo.c54
-rw-r--r--cpukit/score/src/heapgetinfo.c57
-rw-r--r--cpukit/score/src/heapresizeblock.c119
-rw-r--r--cpukit/score/src/heapsizeofuserarea.c58
-rw-r--r--cpukit/score/src/heapwalk.c421
-rw-r--r--cpukit/score/src/interr.c65
-rw-r--r--cpukit/score/src/isr.c83
-rw-r--r--cpukit/score/src/iterateoverthreads.c55
-rw-r--r--cpukit/score/src/mpci.c540
-rw-r--r--cpukit/score/src/objectallocate.c102
-rw-r--r--cpukit/score/src/objectapimaximumclass.c36
-rw-r--r--cpukit/score/src/objectclose.c28
-rw-r--r--cpukit/score/src/objectextendinformation.c266
-rw-r--r--cpukit/score/src/objectfree.c69
-rw-r--r--cpukit/score/src/objectget.c108
-rw-r--r--cpukit/score/src/objectgetinfo.c62
-rw-r--r--cpukit/score/src/objectgetinfoid.c28
-rw-r--r--cpukit/score/src/objectgetisr.c86
-rw-r--r--cpukit/score/src/objectgetnameasstring.c96
-rw-r--r--cpukit/score/src/objectgetnext.c103
-rw-r--r--cpukit/score/src/objectgetnoprotection.c79
-rw-r--r--cpukit/score/src/objectidtoname.c79
-rw-r--r--cpukit/score/src/objectinitializeinformation.c178
-rw-r--r--cpukit/score/src/objectmp.c307
-rw-r--r--cpukit/score/src/objectnamespaceremove.c40
-rw-r--r--cpukit/score/src/objectnametoid.c102
-rw-r--r--cpukit/score/src/objectnametoidstring.c87
-rw-r--r--cpukit/score/src/objectsetname.c69
-rw-r--r--cpukit/score/src/objectshrinkinformation.c102
-rw-r--r--cpukit/score/src/percpu.c64
-rw-r--r--cpukit/score/src/pheapallocate.c46
-rw-r--r--cpukit/score/src/pheapextend.c41
-rw-r--r--cpukit/score/src/pheapfree.c38
-rw-r--r--cpukit/score/src/pheapgetblocksize.c39
-rw-r--r--cpukit/score/src/pheapgetfreeinfo.c42
-rw-r--r--cpukit/score/src/pheapgetinfo.c43
-rw-r--r--cpukit/score/src/pheapgetsize.c32
-rw-r--r--cpukit/score/src/pheapinit.c27
-rw-r--r--cpukit/score/src/pheapresizeblock.c43
-rw-r--r--cpukit/score/src/pheapwalk.c50
-rw-r--r--cpukit/score/src/scheduler.c25
-rw-r--r--cpukit/score/src/schedulerpriority.c33
-rw-r--r--cpukit/score/src/schedulerpriorityallocate.c35
-rw-r--r--cpukit/score/src/schedulerpriorityblock.c42
-rw-r--r--cpukit/score/src/schedulerpriorityenqueue.c26
-rw-r--r--cpukit/score/src/schedulerpriorityenqueuefirst.c27
-rw-r--r--cpukit/score/src/schedulerpriorityextract.c27
-rw-r--r--cpukit/score/src/schedulerpriorityfree.c29
-rw-r--r--cpukit/score/src/schedulerpriorityschedule.c25
-rw-r--r--cpukit/score/src/schedulerpriorityunblock.c48
-rw-r--r--cpukit/score/src/schedulerpriorityupdate.c42
-rw-r--r--cpukit/score/src/schedulerpriorityyield.c55
-rw-r--r--cpukit/score/src/schedulersimple.c84
-rw-r--r--cpukit/score/src/schedulersimpleblock.c39
-rw-r--r--cpukit/score/src/schedulersimpleenqueue.c29
-rw-r--r--cpukit/score/src/schedulersimpleenqueuefirst.c28
-rw-r--r--cpukit/score/src/schedulersimpleextract.c28
-rw-r--r--cpukit/score/src/schedulersimplereadyqueueenqueue.c48
-rw-r--r--cpukit/score/src/schedulersimplereadyqueueenqueuefirst.c52
-rw-r--r--cpukit/score/src/schedulersimpleschedule.c34
-rw-r--r--cpukit/score/src/schedulersimpleunblock.c47
-rw-r--r--cpukit/score/src/schedulersimpleyield.c42
-rw-r--r--cpukit/score/src/smp.c153
-rw-r--r--cpukit/score/src/smplock.c49
-rw-r--r--cpukit/score/src/thread.c123
-rw-r--r--cpukit/score/src/threadblockingoperationcancel.c89
-rw-r--r--cpukit/score/src/threadchangepriority.c99
-rw-r--r--cpukit/score/src/threadclearstate.c58
-rw-r--r--cpukit/score/src/threadclose.c104
-rw-r--r--cpukit/score/src/threadcreateidle.c106
-rw-r--r--cpukit/score/src/threaddelayended.c71
-rw-r--r--cpukit/score/src/threaddispatch.c193
-rw-r--r--cpukit/score/src/threadget.c100
-rw-r--r--cpukit/score/src/threadhandler.c189
-rw-r--r--cpukit/score/src/threadinitialize.c242
-rw-r--r--cpukit/score/src/threadloadenv.c74
-rw-r--r--cpukit/score/src/threadmp.c168
-rw-r--r--cpukit/score/src/threadq.c66
-rw-r--r--cpukit/score/src/threadqdequeue.c72
-rw-r--r--cpukit/score/src/threadqdequeuefifo.c79
-rw-r--r--cpukit/score/src/threadqdequeuepriority.c125
-rw-r--r--cpukit/score/src/threadqenqueue.c97
-rw-r--r--cpukit/score/src/threadqenqueuefifo.c78
-rw-r--r--cpukit/score/src/threadqenqueuepriority.c197
-rw-r--r--cpukit/score/src/threadqextract.c58
-rw-r--r--cpukit/score/src/threadqextractfifo.c78
-rw-r--r--cpukit/score/src/threadqextractpriority.c125
-rw-r--r--cpukit/score/src/threadqextractwithproxy.c67
-rw-r--r--cpukit/score/src/threadqfirst.c54
-rw-r--r--cpukit/score/src/threadqfirstfifo.c50
-rw-r--r--cpukit/score/src/threadqfirstpriority.c57
-rw-r--r--cpukit/score/src/threadqflush.c62
-rw-r--r--cpukit/score/src/threadqprocesstimeout.c57
-rw-r--r--cpukit/score/src/threadqrequeue.c74
-rw-r--r--cpukit/score/src/threadqtimeout.c60
-rw-r--r--cpukit/score/src/threadready.c51
-rw-r--r--cpukit/score/src/threadreset.c67
-rw-r--r--cpukit/score/src/threadrestart.c68
-rw-r--r--cpukit/score/src/threadsetpriority.c30
-rw-r--r--cpukit/score/src/threadsetstate.c58
-rw-r--r--cpukit/score/src/threadsettransient.c56
-rw-r--r--cpukit/score/src/threadstackallocate.c84
-rw-r--r--cpukit/score/src/threadstackfree.c62
-rw-r--r--cpukit/score/src/threadstart.c69
-rw-r--r--cpukit/score/src/threadstartmultitasking.c91
-rw-r--r--cpukit/score/src/threadtickletimeslice.c105
-rw-r--r--cpukit/score/src/timespecaddto.c51
-rw-r--r--cpukit/score/src/timespecdivide.c59
-rw-r--r--cpukit/score/src/timespecdividebyinteger.c53
-rw-r--r--cpukit/score/src/timespecfromticks.c35
-rw-r--r--cpukit/score/src/timespecgreaterthan.c42
-rw-r--r--cpukit/score/src/timespecisvalid.c43
-rw-r--r--cpukit/score/src/timespeclessthan.c42
-rw-r--r--cpukit/score/src/timespecsubtract.c41
-rw-r--r--cpukit/score/src/timespectoticks.c50
-rw-r--r--cpukit/score/src/ts64addto.c34
-rw-r--r--cpukit/score/src/ts64divide.c52
-rw-r--r--cpukit/score/src/ts64dividebyinteger.c35
-rw-r--r--cpukit/score/src/ts64equalto.c34
-rw-r--r--cpukit/score/src/ts64getnanoseconds.c33
-rw-r--r--cpukit/score/src/ts64getseconds.c33
-rw-r--r--cpukit/score/src/ts64greaterthan.c34
-rw-r--r--cpukit/score/src/ts64lessthan.c34
-rw-r--r--cpukit/score/src/ts64set.c39
-rw-r--r--cpukit/score/src/ts64settozero.c33
-rw-r--r--cpukit/score/src/ts64subtract.c35
-rw-r--r--cpukit/score/src/ts64toticks.c40
-rw-r--r--cpukit/score/src/ts64totimespec.c35
-rw-r--r--cpukit/score/src/userext.c61
-rw-r--r--cpukit/score/src/userextaddset.c45
-rw-r--r--cpukit/score/src/userextremoveset.c39
-rw-r--r--cpukit/score/src/userextthreadbegin.c81
-rw-r--r--cpukit/score/src/userextthreadcreate.c52
-rw-r--r--cpukit/score/src/userextthreaddelete.c46
-rw-r--r--cpukit/score/src/userextthreadrestart.c46
-rw-r--r--cpukit/score/src/userextthreadstart.c46
-rw-r--r--cpukit/score/src/userextthreadswitch.c43
-rw-r--r--cpukit/score/src/watchdog.c42
-rw-r--r--cpukit/score/src/watchdogadjust.c87
-rw-r--r--cpukit/score/src/watchdogadjusttochain.c83
-rw-r--r--cpukit/score/src/watchdoginsert.c100
-rw-r--r--cpukit/score/src/watchdognanoseconds.c31
-rw-r--r--cpukit/score/src/watchdogremove.c73
-rw-r--r--cpukit/score/src/watchdogreport.c41
-rw-r--r--cpukit/score/src/watchdogreportchain.c50
-rw-r--r--cpukit/score/src/watchdogtickle.c129
-rw-r--r--cpukit/score/src/wkspace.c125
203 files changed, 16199 insertions, 0 deletions
diff --git a/cpukit/score/src/Unlimited.txt b/cpukit/score/src/Unlimited.txt
new file mode 100644
index 0000000000..47309c361c
--- /dev/null
+++ b/cpukit/score/src/Unlimited.txt
@@ -0,0 +1,364 @@
+#
+# $Id$
+#
+
+This document explains how the unlimited objects support works. This was
+written by Chris Johns <ccj@acm.org> of Objective Design Systems as a
+design document. This was submitted as part of the patch which added
+this capability.
+
+Unlimited Local Node Objects
+============================
+
+1. Why ?
+
+This patch changes the way RTEMS allocates, frees, and manages the
+'Objects_Control' structure.
+
+The 'Objects_Control' structure is at the root of all objects in
+RTEMS. The RTEMS and POSIX API allows users to create tasks, message
+queues, semaphores and other resources. These are all a type of
+Object. The POSIX API allow similar operations. These also map to
+Objects.
+
+Currently the number of objects that can be created is a static value
+loaded into the Configuration table before starting the kernel. The
+application cannot exceed these limits. Various means are used to tune
+this value. During development the value is usually set large. This
+saves having to change it everytime a developer adds a new
+resource. With a large team of developers the configuration table file
+can cycle through a large number of revisions. The wasted memory is
+only recovered when memory runs short. The issue of the configuration
+table parameters become more important the less memory you have.
+
+The Configuration table requires a calculation to occur at compile
+time to set the size of the Workspace. The calculation is an
+estimate. You need to specify an overhead value for memory that can
+not be calculated. An example of memory that cannot be calculated is
+stack sizes. This issue is not directly related to allowing unlimited
+objects how-ever the need to calculate the memory usage for a system
+in this manner is prone to error.
+
+I would like to see download support added to RTEMS. The kernel
+configuration being set at boot time means a download application can
+be limited. This can defeat one of the purposes of using downloaded
+code, no need to change ROMs. In a system I worked on the cost to
+change ROMS in a complete system was high and could take a week. This
+change is the first phase of supporting downloaded applications.
+
+1.1 How do Objects work ?
+
+All applications interact with the super core (c/src/exec/score) via
+an API. The central structure used in the super core is the
+`object'. Two application interfaces exist. They are RTEMS and
+POSIX. Both map to the super core using objects.
+
+An object in RTEMS is a resource which the user (through the API)
+creates. The different types of objects are referred to as classes of
+objects. An object is referenced by an id. This is of type `rtems_id'
+and is a 32bit unsigned integer. The id is unique for each object no
+matter what class.
+
+Objects are anchored by the `_Object_Information' structure. There is
+one per type or class of object. A global table of pointers to each
+information structure for a class of objects is held in
+`Objects_Information_table'.
+
+Objects consist of 6 main structures. The `_Object_Information' is the
+root structure. It contains pointers to the `local_table',
+`name_table', `global_table', the Inactive chain, and the object
+memory. It also contains the various variables which describe the
+object. We are only concerned with the `local_table', `name_table',
+Inactive chain, and the object memory to support unlimited objects.
+
+The `local_table' holds the pointers to open objects. A `local_table
+entry which is null is free and the object will be sitting on the
+Inactive chain. The index into the table is based on part of the
+id. Given an id the you can find the index into the `local_table', and
+therefore the object. The `local_table' has the entries for the
+indexes below the minimum_id's index. The minimum_id is always set to
+1 (the change allows another value to be selected if require). The
+index of 0 is reserved and never used. This allows any actions using
+an id of zero to fail or map to a special case.
+
+The `name_table' holds the names of the objects. Each entry in this
+table is the maximum size the name of the object can be. The size of
+names is not constrained by the object code (but is by the MP object
+code, and the API and should be fixed).
+
+The `global_table' and code that uses it has not changed. I did not
+look at the this code, and I am not farmilar with it.
+
+The Inactive chain stores objects which are free or not
+allocated. This design saves searching for a free object when
+allocating therefore providing a deterministic allocation scheme. When
+the chain is empty a null is returned.
+
+The change documented below basically extends the `local_table' and
+`name_table' structures at run-time. The memory used be these table
+is not large compared to the memory for the objects, and so are never
+reduced in size once extended. The object's memory grows and shrinks
+depending of the user's usage.
+
+Currently, the user specifies the total number of objects in the
+Configuration table. The change alters the function of the values in
+the Configuration table. A flag can be masked on to the value which
+selects the extending mode. If the user does not set the flag the
+object code operates with an object ceiling. A small performance
+overhead will be incurred as the allocate and free routines are now
+not inlined and a check of the auto_extend flag is made. The remaining
+value field of the Configuration table entry is total number of
+objects that can be allocated when not in unlimited mode.
+
+If the user masks the flag on to a value on the Configuration table
+auto-exdending mode is selected for that class of object. The value
+becomes the allocation unit size. If there are no free objects the
+object's tables are extended by the allocation unit number of
+objects. The object table is shrunk when the user frees objects. The
+table must have one free allocation block, and at least half the
+allocation size of another block before the object memory of the free
+allocation block is returned to the heap. This stops threshold
+thrashing when objects around the allocation unit size and created and
+destroyed.
+
+At least one allocation block size of objects is created and never
+destroyed.
+
+The change to support unlimited objects has extended the object
+information structure.
+
+The flag, `auto_extend' controls if the object can be automatically
+extended. The user masks the flag RTEMS_UNLIMITED_FLAGS onto the
+Configuration table number to select the auto-extend mode. This is
+passed to the `_Objects_Initialize_information' function in the
+parameter maximum. The flag is tested for and the auto_extend flag
+updated to reflect the state of the flag before being stipped from the
+maximum.
+
+The `allocation_size' is set to the parameter maxium in the function
+`_Objects_Initialize_information' if `auto_extend' is true. Making the
+allocation size small causes the memory to be allocated and freed more
+often. This only effects the performance times for creating a resource
+such as a task. It does how-ever give you fine grain memory
+control. If the performance of creating resources is not a problem
+make the size small.
+
+The size of the object is required to be stored. It is used when
+extending the object information.
+
+A count of the object on the Inactive list is maintained. This is used
+during freeing objects. If the count is above 1.5 times the
+`allocation_size' an attempt is made to shrink the object
+informtation. Shrinking might not always succeed as a single
+allocation block might not be free. Random freeing of objects can
+result in some fragmentation. Any further allocations will use the
+free objects before extending the object's information tables.
+
+A table of inactive objects per block is maintained. This table, like
+the `local_table' and `name_table' grows as more blocks are
+allocated. A check is made of a blocks inactive count when an object
+which is part of that block is freed. If the total inactive count
+exceeds 1.5 times the allocation size, and the block's inactive count
+is the allocation_size, the objects data block is returnd to the
+workspace heap.
+
+The `objects_blocks' is a table of pointers. The object_block's pointers
+point to the object's data block. The object's data block is a single
+allocation of the name space and object space. This was two separate
+allocations but is now one. The objects_block's table is use to
+determine if a block is allocated, and the address of the memory block
+to be returned to the workspace heap when the object informtation
+space is shrunk.
+
+2.0 Detail Of the Auto-Extend Patch to rtems-4.0.0, Snapshot 19990302
+
+o Configuration table support.
+
+ Added a flag OBJECTS_UNLIMITED_OBJECTS to score/headers/object.h
+ header file. This is referenced in the file sapi/headers/config.h to
+ create the flag RTEMS_UNLIMITED_OBJECTS. A macro is provided to take
+ a resource count and apply the flag. The macro is called
+ `rtems_resource_unlimited'. The user uses this macro when building a
+ configuration table. It can be used with the condefs.h header file.
+
+o Object Information Structure
+
+ The object information structure, Objects_Information, has been
+ extended with the follow fields :
+
+ boolean auto_extend -
+
+ When true the object's information tables can be extended untill
+ all memory is used. When false the current functionallity is
+ maintained.
+
+ uint32_t allocation_size -
+
+ When auto_extend is true, it is the value in the Configuration
+ table and is the number of objects the object's information
+ tables are extended or shrunk.
+
+ uint32_t size -
+
+ The size of the object. It is used to calculate the size of
+ memory required to be allocated when extending the table.
+
+ uint32_t inactive -
+
+ The number of elements on the Inactive chain.
+
+ uint32_t *inactive_per_block -
+
+ Pointer to a table of counts of the inactive objects from a
+ block on the Inactive chain. It is used to know which blocks are
+ all free and therefore can be returned to the heap.
+
+ void **object_blocks -
+
+ Pointer to a table of pointers to the object data. The table
+ holds the pointer used to return a block to the heap when
+ shrinking the object's information tables.
+
+o Changes to Existing Object Functions
+
+ Two functions prototypes are added. They are :
+
+ _Objects_Extend_information,
+ _Objects_Shrink_information
+ _Object_Allocate, and
+ _Object_Free
+
+ The last were inlined, how-ever now they are not as they are too
+ complex to implement as macros now.
+
+o Object Initialisation
+
+ The function _Objects_Initialize_information has been changed to
+ initialisation of the information structure's fields then call the
+ new function _Objects_Extend_information.
+
+ The first block of objects is always allocated and never
+ released. This means with the auto-extend flag set to true the user
+ still sees the same behaviour expected without this change. That is
+ the number objects specified in the Configuration table is the
+ number of object allocated during RTEMS initialisation. If not
+ enough memory is found during this initial extend a fatal error
+ occurs. The fatal error only occurs for this case of extending the
+ object's information tables.
+
+o Object Information Extend
+
+ The _Object_Information_Extend is a new function. It takes some of
+ the code form the old _Object_Initialize_information function. The
+ function extends an object's information base.
+
+ Extending the first time is a special case. The function assumes the
+ maximum index will be less than the minimum index. This means the
+ minimum index must be greater than 0 at initialisation. The other
+ special case made is coping the tables from the old location to the
+ new location. The first block case is trapped and tables are
+ initialised instead. Workspace allocation for the first block is
+ tested for an if the first block the allocate or fatal error call is
+ made. This traps an RTEMS initialise allocation error.
+
+ The remainder of the code deals with all cases of extending the
+ object's information.
+
+ The current block count is first determined, then a scan of the
+ object_block table is made to locate a free slot. Blocks can be
+ freed in any order. The index base for the block is also determined.
+
+ If the index base is greater than the maximum index, the tables must
+ grow. To grow the tables, a new larger memory block is allocated and
+ the tables copied. The object's information structure is then
+ updated to point to the new tables. The tables are allocated in one
+ memory block from the work-space heap. The single block is then
+ broken down in the required tables.
+
+ Once the tables are copied, and the new extended parts initialised
+ the table pointers in the object's information structure are
+ updated. This is protected by masking interrupts.
+
+ The old table's memory block is returned to the heap.
+
+ The names table and object is allocated. This again is a single
+ block which is divided.
+
+ The objects are initialised onto a local Inactive chain. They are
+ then copied to the object's Inactive chain to complete the
+ initialisation.
+
+o Object Informtation Shrink
+
+ The _Object_Shrink_information function is new. It is required to
+ scan all the blocks to see which one has no objects allocated. The
+ last object freed might not belong to a block which is completely
+ free.
+
+ Once a block is located, the Inactive chain is interated down
+ looking for objects which belong to the block of object being
+ released.
+
+ Once the Inactive chain scan is complete the names table and object
+ memory is returned to the work-space heap and the table references cleared.
+
+ XXX - I am not sure if this should occur if better protection or
+ different code to provide better protection.
+
+ The information tables do not change size. Once extended they never
+ shrink.
+
+o Object Allocation
+
+ The _Objects_Allocate attempts to get an object from the Inactive
+ chain. If auto-extend mode is not enabled no further processing
+ occurs. The extra overhead for this implemetation is the function is
+ not inlined and check of a boolean occurs. It should effect the
+ timing figures.
+
+ If auto-extend is enabled, a further check is made to see if the get
+ from the Inactive chain suceeded in getting an object. If it failed
+ a call is made to extend the object's information tables.
+
+ The get from the Inactive chain is retried. The result of this is
+ returned to the user. A failure here is the users problem.
+
+o Object Free
+
+ The _Objects_Free puts the object back onto the Inactive
+ chain. Again if auto-extend mode is not enabled no further
+ processing occurs and performance overhead will low.
+
+ If auto-extend mode is enabled, a check is to see if the number of
+ Inactive objects is one and a half times the allocation size. If
+ there are that many free objects an attempt is made to shrink the
+ object's information.
+
+o Object Index and the Get Function
+
+ The existing code allocates the number of object specified in the
+ configuration table, how-ever it makes the local_table have one more
+ element. This is the slot for an id of 0. The 0 slot is always a
+ NULL providing a simple check for a 0 id for object classes.
+
+ The existing _Objects_Get code removes the minimum id, which I think
+ could only be 1 from the index, then adds one for the 0 slot.
+
+ This change removes this index adjustment code in _Objects_Get.
+
+ The extend information starts the index count when scanning for free
+ blocks at the minumun index. This means the base index for a block
+ will always be adjusted by the minimum index. The extend information
+ function only ever allocates the allocation size of
+ objects. Finially the object's local_table size is the maximum plus
+ the minumum index size. The maximum is really the maximum index.
+
+ This means the values in the object's information structure and
+ tables do not need the index adjustments which existed before.
+
+o The Test
+
+ A new sample test, unlimited is provided. It attempts to test this
+ change.
+
+
diff --git a/cpukit/score/src/apiext.c b/cpukit/score/src/apiext.c
new file mode 100644
index 0000000000..a08977113e
--- /dev/null
+++ b/cpukit/score/src/apiext.c
@@ -0,0 +1,113 @@
+/* apiext.c
+ *
+ * XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+
+/*PAGE
+ *
+ * _API_extensions_Initialization
+ */
+
+void _API_extensions_Initialization( void )
+{
+ _Chain_Initialize_empty( &_API_extensions_List );
+}
+
+/*PAGE
+ *
+ * _API_extensions_Add
+ */
+
+void _API_extensions_Add(
+ API_extensions_Control *the_extension
+)
+{
+ _Chain_Append( &_API_extensions_List, &the_extension->Node );
+}
+
+#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
+ /*PAGE
+ *
+ * _API_extensions_Run_predriver
+ */
+
+ void _API_extensions_Run_predriver( void )
+ {
+ Chain_Node *the_node;
+ API_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_First( &_API_extensions_List );
+ !_Chain_Is_tail( &_API_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (API_extensions_Control *) the_node;
+
+ if ( the_extension->predriver_hook )
+ (*the_extension->predriver_hook)();
+ }
+ }
+#endif
+
+/*PAGE
+ *
+ * _API_extensions_Run_postdriver
+ */
+
+void _API_extensions_Run_postdriver( void )
+{
+ Chain_Node *the_node;
+ API_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_First( &_API_extensions_List );
+ !_Chain_Is_tail( &_API_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (API_extensions_Control *) the_node;
+
+ /*
+ * Currently all APIs configure this hook so it is always non-NULL.
+ */
+#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
+ if ( the_extension->postdriver_hook )
+#endif
+ (*the_extension->postdriver_hook)();
+ }
+}
+
+/*PAGE
+ *
+ * _API_extensions_Run_postswitch
+ */
+
+void _API_extensions_Run_postswitch( void )
+{
+ Chain_Node *the_node;
+ API_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_First( &_API_extensions_List );
+ !_Chain_Is_tail( &_API_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (API_extensions_Control *) the_node;
+
+ (*the_extension->postswitch_hook)( _Thread_Executing );
+ }
+}
+
+/* end of file */
diff --git a/cpukit/score/src/apimutex.c b/cpukit/score/src/apimutex.c
new file mode 100644
index 0000000000..93e67eafaf
--- /dev/null
+++ b/cpukit/score/src/apimutex.c
@@ -0,0 +1,37 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apimutex.h>
+
+void _API_Mutex_Initialization(
+ uint32_t maximum_mutexes
+)
+{
+ _Objects_Initialize_information(
+ &_API_Mutex_Information, /* object information table */
+ OBJECTS_INTERNAL_API, /* object API */
+ OBJECTS_INTERNAL_MUTEXES, /* object class */
+ maximum_mutexes, /* maximum objects of this class */
+ sizeof( API_Mutex_Control ), /* size of this object's control block */
+ false, /* true if the name is a string */
+ 0 /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ true, /* true if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/score/src/apimutexallocate.c b/cpukit/score/src/apimutexallocate.c
new file mode 100644
index 0000000000..5a2a323315
--- /dev/null
+++ b/cpukit/score/src/apimutexallocate.c
@@ -0,0 +1,39 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apimutex.h>
+
+void _API_Mutex_Allocate(
+ API_Mutex_Control **the_mutex
+)
+{
+ API_Mutex_Control *mutex;
+
+ CORE_mutex_Attributes attr = {
+ CORE_MUTEX_NESTING_ACQUIRES,
+ false,
+ CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
+ 0
+ };
+
+ mutex = (API_Mutex_Control *) _Objects_Allocate( &_API_Mutex_Information );
+
+ _CORE_mutex_Initialize( &mutex->Mutex, &attr, CORE_MUTEX_UNLOCKED );
+
+ _Objects_Open_u32( &_API_Mutex_Information, &mutex->Object, 1 );
+
+ *the_mutex = mutex;
+}
diff --git a/cpukit/score/src/apimutexlock.c b/cpukit/score/src/apimutexlock.c
new file mode 100644
index 0000000000..6729478ae4
--- /dev/null
+++ b/cpukit/score/src/apimutexlock.c
@@ -0,0 +1,34 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apimutex.h>
+
+void _API_Mutex_Lock(
+ API_Mutex_Control *the_mutex
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ _CORE_mutex_Seize(
+ &the_mutex->Mutex,
+ the_mutex->Object.id,
+ true,
+ 0,
+ level
+ );
+}
diff --git a/cpukit/score/src/apimutexunlock.c b/cpukit/score/src/apimutexunlock.c
new file mode 100644
index 0000000000..ca824a6e6c
--- /dev/null
+++ b/cpukit/score/src/apimutexunlock.c
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apimutex.h>
+
+void _API_Mutex_Unlock(
+ API_Mutex_Control *the_mutex
+)
+{
+ _Thread_Disable_dispatch();
+ _CORE_mutex_Surrender(
+ &the_mutex->Mutex,
+ the_mutex->Object.id,
+ NULL
+ );
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/score/src/chain.c b/cpukit/score/src/chain.c
new file mode 100644
index 0000000000..85821d4d71
--- /dev/null
+++ b/cpukit/score/src/chain.c
@@ -0,0 +1,61 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Chain_Initialize
+ *
+ * This kernel routine initializes a doubly linked chain.
+ *
+ * Input parameters:
+ * the_chain - pointer to chain header
+ * starting_address - starting address of first node
+ * number_nodes - number of nodes in chain
+ * node_size - size of node in bytes
+ *
+ * Output parameters: NONE
+ */
+
+void _Chain_Initialize(
+ Chain_Control *the_chain,
+ void *starting_address,
+ size_t number_nodes,
+ size_t node_size
+)
+{
+ size_t count = number_nodes;
+ Chain_Node *head = _Chain_Head( the_chain );
+ Chain_Node *tail = _Chain_Tail( the_chain );
+ Chain_Node *current = head;
+ Chain_Node *next = starting_address;
+
+ head->previous = NULL;
+
+ while ( count-- ) {
+ current->next = next;
+ next->previous = current;
+ current = next;
+ next = (Chain_Node *)
+ _Addresses_Add_offset( (void *) next, node_size );
+ }
+
+ current->next = tail;
+ tail->previous = current;
+}
diff --git a/cpukit/score/src/chainappend.c b/cpukit/score/src/chainappend.c
new file mode 100644
index 0000000000..f5287a450f
--- /dev/null
+++ b/cpukit/score/src/chainappend.c
@@ -0,0 +1,46 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*
+ * _Chain_Append
+ *
+ * This kernel routine puts a node on the end of the specified chain.
+ *
+ * Input parameters:
+ * the_chain - pointer to chain header
+ * node - address of node to put at rear of chain
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Chain_Append(
+ Chain_Control *the_chain,
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Chain_Append_unprotected( the_chain, node );
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/chainappendempty.c b/cpukit/score/src/chainappendempty.c
new file mode 100644
index 0000000000..33033df8ed
--- /dev/null
+++ b/cpukit/score/src/chainappendempty.c
@@ -0,0 +1,44 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreChain
+ *
+ * @brief _Chain_Append_with_empty_check() implementation.
+ */
+
+/*
+ * Copyright (c) 2010 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+bool _Chain_Append_with_empty_check(
+ Chain_Control *chain,
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+ bool was_empty;
+
+ _ISR_Disable( level );
+ was_empty = _Chain_Append_with_empty_check_unprotected( chain, node );
+ _ISR_Enable( level );
+
+ return was_empty;
+}
diff --git a/cpukit/score/src/chainextract.c b/cpukit/score/src/chainextract.c
new file mode 100644
index 0000000000..deb537ed85
--- /dev/null
+++ b/cpukit/score/src/chainextract.c
@@ -0,0 +1,44 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*
+ * _Chain_Extract
+ *
+ * This kernel routine deletes the given node from a chain.
+ *
+ * Input parameters:
+ * node - pointer to node in chain to be deleted
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Chain_Extract(
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Chain_Extract_unprotected( node );
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/chainget.c b/cpukit/score/src/chainget.c
new file mode 100644
index 0000000000..4ec11c112e
--- /dev/null
+++ b/cpukit/score/src/chainget.c
@@ -0,0 +1,51 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*
+ * _Chain_Get
+ *
+ * This kernel routine returns a pointer to a node taken from the
+ * given chain.
+ *
+ * Input parameters:
+ * the_chain - pointer to chain header
+ *
+ * Output parameters:
+ * return_node - pointer to node in chain allocated
+ * CHAIN_END - if no nodes available
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+Chain_Node *_Chain_Get(
+ Chain_Control *the_chain
+)
+{
+ ISR_Level level;
+ Chain_Node *return_node;
+
+ return_node = NULL;
+ _ISR_Disable( level );
+ if ( !_Chain_Is_empty( the_chain ) )
+ return_node = _Chain_Get_first_unprotected( the_chain );
+ _ISR_Enable( level );
+ return return_node;
+}
diff --git a/cpukit/score/src/chaingetempty.c b/cpukit/score/src/chaingetempty.c
new file mode 100644
index 0000000000..3f9be4de5b
--- /dev/null
+++ b/cpukit/score/src/chaingetempty.c
@@ -0,0 +1,44 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreChain
+ *
+ * @brief _Chain_Get_with_empty_check() implementation.
+ */
+
+/*
+ * Copyright (c) 2010 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+bool _Chain_Get_with_empty_check(
+ Chain_Control *chain,
+ Chain_Node **node
+)
+{
+ ISR_Level level;
+ bool is_empty_now;
+
+ _ISR_Disable( level );
+ is_empty_now = _Chain_Get_with_empty_check_unprotected( chain, node );
+ _ISR_Enable( level );
+
+ return is_empty_now;
+}
diff --git a/cpukit/score/src/chaininsert.c b/cpukit/score/src/chaininsert.c
new file mode 100644
index 0000000000..0f5cdd25ab
--- /dev/null
+++ b/cpukit/score/src/chaininsert.c
@@ -0,0 +1,47 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*
+ * _Chain_Insert
+ *
+ * This kernel routine inserts a given node after a specified node
+ * a requested chain.
+ *
+ * Input parameters:
+ * after_node - pointer to node in chain to be inserted after
+ * node - pointer to node to be inserted
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Chain_Insert(
+ Chain_Node *after_node,
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Chain_Insert_unprotected( after_node, node );
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/chainprependempty.c b/cpukit/score/src/chainprependempty.c
new file mode 100644
index 0000000000..9dfd9a653f
--- /dev/null
+++ b/cpukit/score/src/chainprependempty.c
@@ -0,0 +1,44 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreChain
+ *
+ * @brief _Chain_Prepend_with_empty_check() implementation.
+ */
+
+/*
+ * Copyright (c) 2010 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+bool _Chain_Prepend_with_empty_check(
+ Chain_Control *chain,
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+ bool was_empty;
+
+ _ISR_Disable( level );
+ was_empty = _Chain_Prepend_with_empty_check_unprotected( chain, node );
+ _ISR_Enable( level );
+
+ return was_empty;
+}
diff --git a/cpukit/score/src/corebarrier.c b/cpukit/score/src/corebarrier.c
new file mode 100644
index 0000000000..55f093ccc3
--- /dev/null
+++ b/cpukit/score/src/corebarrier.c
@@ -0,0 +1,57 @@
+/*
+ * SuperCore Barrier Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is part of the implementation of the SuperCore Barrier Handler.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corebarrier.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_barrier_Initialize
+ *
+ * This function initialize a barrier and sets the initial value based
+ * on the given count.
+ *
+ * Input parameters:
+ * the_barrier - the barrier control block to initialize
+ * the_barrier_attributes - the attributes specified at create time
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_barrier_Initialize(
+ CORE_barrier_Control *the_barrier,
+ CORE_barrier_Attributes *the_barrier_attributes
+)
+{
+
+ the_barrier->Attributes = *the_barrier_attributes;
+ the_barrier->number_of_waiting_threads = 0;
+
+ _Thread_queue_Initialize(
+ &the_barrier->Wait_queue,
+ THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_BARRIER,
+ CORE_BARRIER_TIMEOUT
+ );
+}
diff --git a/cpukit/score/src/corebarrierrelease.c b/cpukit/score/src/corebarrierrelease.c
new file mode 100644
index 0000000000..7bf341d4c7
--- /dev/null
+++ b/cpukit/score/src/corebarrierrelease.c
@@ -0,0 +1,70 @@
+/*
+ * SuperCore Barrier Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is part of the implementation of the SuperCore Barrier Handler.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/corebarrier.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_barrier_Release
+ *
+ * Input parameters:
+ * the_barrier - the barrier to be flushed
+ * id - id of the object for a remote unblock
+ * api_barrier_mp_support - api dependent MP support actions
+ *
+ * Output parameters:
+ * CORE_BARRIER_STATUS_SUCCESSFUL - if successful
+ * core error code - if unsuccessful
+ *
+ * Output parameters:
+ * returns number of threads unblocked
+ */
+
+uint32_t _CORE_barrier_Release(
+ CORE_barrier_Control *the_barrier,
+#if defined(RTEMS_MULTIPROCESSING)
+ Objects_Id id,
+ CORE_barrier_API_mp_support_callout api_barrier_mp_support
+#else
+ Objects_Id id __attribute__((unused)),
+ CORE_barrier_API_mp_support_callout api_barrier_mp_support __attribute__((unused))
+#endif
+)
+{
+ Thread_Control *the_thread;
+ uint32_t count;
+
+ count = 0;
+ while ( (the_thread = _Thread_queue_Dequeue(&the_barrier->Wait_queue)) ) {
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_barrier_mp_support) ( the_thread, id );
+#endif
+ count++;
+ }
+ the_barrier->number_of_waiting_threads = 0;
+ return count;
+}
diff --git a/cpukit/score/src/corebarrierwait.c b/cpukit/score/src/corebarrierwait.c
new file mode 100644
index 0000000000..4db276f1ce
--- /dev/null
+++ b/cpukit/score/src/corebarrierwait.c
@@ -0,0 +1,78 @@
+/*
+ * SuperCore Barrier Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is part of the implementation of the SuperCore Barrier Handler.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/corebarrier.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_barrier_Wait
+ *
+ * Input parameters:
+ * the_barrier - pointer to barrier control block
+ * id - id of object to wait on
+ * wait - true if wait is allowed, false otherwise
+ * timeout - number of ticks to wait (0 means forever)
+ * api_barrier_mp_support - api dependent MP support actions
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * available
+ * wait
+ */
+
+void _CORE_barrier_Wait(
+ CORE_barrier_Control *the_barrier,
+ Objects_Id id,
+ bool wait,
+ Watchdog_Interval timeout,
+ CORE_barrier_API_mp_support_callout api_barrier_mp_support
+)
+{
+ Thread_Control *executing;
+ ISR_Level level;
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL;
+ _ISR_Disable( level );
+ the_barrier->number_of_waiting_threads++;
+ if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) {
+ if ( the_barrier->number_of_waiting_threads ==
+ the_barrier->Attributes.maximum_count) {
+ executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
+ _ISR_Enable( level );
+ _CORE_barrier_Release( the_barrier, id, api_barrier_mp_support );
+ return;
+ }
+ }
+
+ _Thread_queue_Enter_critical_section( &the_barrier->Wait_queue );
+ executing->Wait.queue = &the_barrier->Wait_queue;
+ executing->Wait.id = id;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_barrier->Wait_queue, timeout );
+}
diff --git a/cpukit/score/src/coremsg.c b/cpukit/score/src/coremsg.c
new file mode 100644
index 0000000000..4e3b9545e1
--- /dev/null
+++ b/cpukit/score/src/coremsg.c
@@ -0,0 +1,120 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _CORE_message_queue_Initialize
+ *
+ * This routine initializes a newly created message queue based on the
+ * specified data.
+ *
+ * Input parameters:
+ * the_message_queue - the message queue to initialize
+ * the_class - the API specific object class
+ * the_message_queue_attributes - the message queue's attributes
+ * maximum_pending_messages - maximum message and reserved buffer count
+ * maximum_message_size - maximum size of each message
+ *
+ * Output parameters:
+ * true - if the message queue is initialized
+ * false - if the message queue is NOT initialized
+ */
+
+bool _CORE_message_queue_Initialize(
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Attributes *the_message_queue_attributes,
+ uint32_t maximum_pending_messages,
+ size_t maximum_message_size
+)
+{
+ size_t message_buffering_required;
+ size_t allocated_message_size;
+
+ the_message_queue->maximum_pending_messages = maximum_pending_messages;
+ the_message_queue->number_of_pending_messages = 0;
+ the_message_queue->maximum_message_size = maximum_message_size;
+ _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL );
+
+ /*
+ * Round size up to multiple of a pointer for chain init and
+ * check for overflow on adding overhead to each message.
+ */
+ allocated_message_size = maximum_message_size;
+ if (allocated_message_size & (sizeof(uint32_t) - 1)) {
+ allocated_message_size += sizeof(uint32_t);
+ allocated_message_size &= ~(sizeof(uint32_t) - 1);
+ }
+
+ if (allocated_message_size < maximum_message_size)
+ return false;
+
+ /*
+ * Calculate how much total memory is required for message buffering and
+ * check for overflow on the multiplication.
+ */
+ message_buffering_required = (size_t) maximum_pending_messages *
+ (allocated_message_size + sizeof(CORE_message_queue_Buffer_control));
+
+ if (message_buffering_required < allocated_message_size)
+ return false;
+
+ /*
+ * Attempt to allocate the message memory
+ */
+ the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
+ _Workspace_Allocate( message_buffering_required );
+
+ if (the_message_queue->message_buffers == 0)
+ return false;
+
+ /*
+ * Initialize the pool of inactive messages, pending messages,
+ * and set of waiting threads.
+ */
+ _Chain_Initialize (
+ &the_message_queue->Inactive_messages,
+ the_message_queue->message_buffers,
+ (size_t) maximum_pending_messages,
+ allocated_message_size + sizeof( CORE_message_queue_Buffer_control )
+ );
+
+ _Chain_Initialize_empty( &the_message_queue->Pending_messages );
+
+ _Thread_queue_Initialize(
+ &the_message_queue->Wait_queue,
+ _CORE_message_queue_Is_priority( the_message_queue_attributes ) ?
+ THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_MESSAGE,
+ CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
+ );
+
+ return true;
+}
diff --git a/cpukit/score/src/coremsgbroadcast.c b/cpukit/score/src/coremsgbroadcast.c
new file mode 100644
index 0000000000..f8f76b0a38
--- /dev/null
+++ b/cpukit/score/src/coremsgbroadcast.c
@@ -0,0 +1,116 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Broadcast
+ *
+ * This function sends a message for every thread waiting on the queue and
+ * returns the number of threads made ready by the message.
+ *
+ * Input parameters:
+ * the_message_queue - message is submitted to this message queue
+ * buffer - pointer to message buffer
+ * size - size in bytes of message to send
+ * id - id of message queue
+ * api_message_queue_mp_support - api specific mp support callout
+ * count - area to store number of threads made ready
+ *
+ * Output parameters:
+ * count - number of threads made ready
+ * CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+CORE_message_queue_Status _CORE_message_queue_Broadcast(
+ CORE_message_queue_Control *the_message_queue,
+ const void *buffer,
+ size_t size,
+ #if defined(RTEMS_MULTIPROCESSING)
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ #else
+ Objects_Id id __attribute__((unused)),
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support __attribute__((unused)),
+ #endif
+ uint32_t *count
+)
+{
+ Thread_Control *the_thread;
+ uint32_t number_broadcasted;
+ Thread_Wait_information *waitp;
+
+ if ( size > the_message_queue->maximum_message_size ) {
+ return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
+ }
+
+ /*
+ * If there are pending messages, then there can't be threads
+ * waiting for us to send them a message.
+ *
+ * NOTE: This check is critical because threads can block on
+ * send and receive and this ensures that we are broadcasting
+ * the message to threads waiting to receive -- not to send.
+ */
+
+ if ( the_message_queue->number_of_pending_messages != 0 ) {
+ *count = 0;
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ }
+
+ /*
+ * There must be no pending messages if there is a thread waiting to
+ * receive a message.
+ */
+ number_broadcasted = 0;
+ while ((the_thread =
+ _Thread_queue_Dequeue(&the_message_queue->Wait_queue))) {
+ waitp = &the_thread->Wait;
+ number_broadcasted += 1;
+
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ waitp->return_argument_second.mutable_object,
+ size
+ );
+
+ *(size_t *) the_thread->Wait.return_argument = size;
+
+ #if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_message_queue_mp_support) ( the_thread, id );
+ #endif
+
+ }
+ *count = number_broadcasted;
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/coremsgclose.c b/cpukit/score/src/coremsgclose.c
new file mode 100644
index 0000000000..b4622598b5
--- /dev/null
+++ b/cpukit/score/src/coremsgclose.c
@@ -0,0 +1,77 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Close
+ *
+ * This function closes a message by returning all allocated space and
+ * flushing the message_queue's task wait queue.
+ *
+ * Input parameters:
+ * the_message_queue - the message_queue to be flushed
+ * remote_extract_callout - function to invoke remotely
+ * status - status to pass to thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_message_queue_Close(
+ CORE_message_queue_Control *the_message_queue,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+
+ /*
+ * This will flush blocked threads whether they were blocked on
+ * a send or receive.
+ */
+
+ _Thread_queue_Flush(
+ &the_message_queue->Wait_queue,
+ remote_extract_callout,
+ status
+ );
+
+ /*
+ * This removes all messages from the pending message queue. Since
+ * we just flushed all waiting threads, we don't have to worry about
+ * the flush satisfying any blocked senders as a side-effect.
+ */
+
+ if ( the_message_queue->number_of_pending_messages != 0 )
+ (void) _CORE_message_queue_Flush_support( the_message_queue );
+
+ (void) _Workspace_Free( the_message_queue->message_buffers );
+
+}
diff --git a/cpukit/score/src/coremsgflush.c b/cpukit/score/src/coremsgflush.c
new file mode 100644
index 0000000000..44bf059b89
--- /dev/null
+++ b/cpukit/score/src/coremsgflush.c
@@ -0,0 +1,55 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Flush
+ *
+ * This function flushes the message_queue's pending message queue. The
+ * number of messages flushed from the queue is returned.
+ *
+ * Input parameters:
+ * the_message_queue - the message_queue to be flushed
+ *
+ * Output parameters:
+ * returns - the number of messages flushed from the queue
+ */
+
+uint32_t _CORE_message_queue_Flush(
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ if ( the_message_queue->number_of_pending_messages != 0 )
+ return _CORE_message_queue_Flush_support( the_message_queue );
+ else
+ return 0;
+}
diff --git a/cpukit/score/src/coremsgflushsupp.c b/cpukit/score/src/coremsgflushsupp.c
new file mode 100644
index 0000000000..4e15e1a495
--- /dev/null
+++ b/cpukit/score/src/coremsgflushsupp.c
@@ -0,0 +1,106 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Flush_support
+ *
+ * This message handler routine removes all messages from a message queue
+ * and returns them to the inactive message pool. The number of messages
+ * flushed from the queue is returned
+ *
+ * Input parameters:
+ * the_message_queue - pointer to message queue
+ *
+ * Output parameters:
+ * returns - number of messages placed on inactive chain
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+uint32_t _CORE_message_queue_Flush_support(
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ ISR_Level level;
+ Chain_Node *inactive_head;
+ Chain_Node *inactive_first;
+ Chain_Node *message_queue_first;
+ Chain_Node *message_queue_last;
+ uint32_t count;
+
+ /*
+ * Currently, RTEMS supports no API that has both flush and blocking
+ * sends. Thus, this routine assumes that there are no senders
+ * blocked waiting to send messages. In the event, that an API is
+ * added that can flush a message queue when threads are blocked
+ * waiting to send, there are two basic behaviors envisioned:
+ *
+ * (1) The thread queue of pending senders is a logical extension
+ * of the pending message queue. In this case, it should be
+ * flushed using the _Thread_queue_Flush() service with a status
+ * such as CORE_MESSAGE_QUEUE_SENDER_FLUSHED (which currently does
+ * not exist). This can be implemented without changing the "big-O"
+ * of the message flushing part of the routine.
+ *
+ * (2) Only the actual messages queued should be purged. In this case,
+ * the blocked sender threads must be allowed to send their messages.
+ * In this case, the implementation will be forced to individually
+ * dequeue the senders and queue their messages. This will force
+ * this routine to have "big O(n)" where n is the number of blocked
+ * senders. If there are more messages pending than senders blocked,
+ * then the existing flush code can be used to dispose of the remaining
+ * pending messages.
+ *
+ * For now, though, we are very happy to have a small routine with
+ * fixed execution time that only deals with pending messages.
+ */
+
+ _ISR_Disable( level );
+ inactive_head = _Chain_Head( &the_message_queue->Inactive_messages );
+ inactive_first = inactive_head->next;;
+ message_queue_first = _Chain_First( &the_message_queue->Pending_messages );
+ message_queue_last = _Chain_Last( &the_message_queue->Pending_messages );
+
+ inactive_head->next = message_queue_first;
+ message_queue_last->next = inactive_first;
+ inactive_first->previous = message_queue_last;
+ message_queue_first->previous = inactive_head;
+
+ _Chain_Initialize_empty( &the_message_queue->Pending_messages );
+
+ count = the_message_queue->number_of_pending_messages;
+ the_message_queue->number_of_pending_messages = 0;
+ _ISR_Enable( level );
+ return count;
+}
diff --git a/cpukit/score/src/coremsgflushwait.c b/cpukit/score/src/coremsgflushwait.c
new file mode 100644
index 0000000000..d7b3c00f5f
--- /dev/null
+++ b/cpukit/score/src/coremsgflushwait.c
@@ -0,0 +1,72 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+#if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
+ /*PAGE
+ *
+ * _CORE_message_queue_Flush_waiting_threads
+ *
+ * This function flushes the message_queue's task wait queue. The number
+ * of messages flushed from the queue is returned.
+ *
+ * Input parameters:
+ * the_message_queue - the message_queue to be flushed
+ *
+ * Output parameters:
+ * returns - the number of messages flushed from the queue
+ */
+
+ void _CORE_message_queue_Flush_waiting_threads(
+ CORE_message_queue_Control *the_message_queue
+ )
+ {
+ /* XXX this is not supported for global message queues */
+
+ /*
+ * IF there are no pending messages,
+ * THEN threads may be blocked waiting to RECEIVE a message,
+ *
+ * IF the pending message queue is full
+ * THEN threads may be blocked waiting to SEND a message
+ *
+ * But in either case, we will return "unsatisfied nowait"
+ * to indicate that the blocking condition was not satisfied
+ * and that the blocking state was canceled.
+ */
+
+ _Thread_queue_Flush(
+ &the_message_queue->Wait_queue,
+ NULL,
+ CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT
+ );
+ }
+#endif
diff --git a/cpukit/score/src/coremsginsert.c b/cpukit/score/src/coremsginsert.c
new file mode 100644
index 0000000000..d333a5fb55
--- /dev/null
+++ b/cpukit/score/src/coremsginsert.c
@@ -0,0 +1,133 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-2005.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Insert_message
+ *
+ * This kernel routine inserts the specified message into the
+ * message queue. It is assumed that the message has been filled
+ * in before this routine is called.
+ *
+ * Input parameters:
+ * the_message_queue - pointer to message queue
+ * the_message - message to insert
+ * priority - insert indication
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * insert
+ */
+
+void _CORE_message_queue_Insert_message(
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Buffer_control *the_message,
+ CORE_message_queue_Submit_types submit_type
+)
+{
+ ISR_Level level;
+ #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
+ bool notify = false;
+ #define SET_NOTIFY() \
+ do { \
+ if ( the_message_queue->number_of_pending_messages == 0 ) \
+ notify = true; \
+ } while (0)
+ #else
+ #define SET_NOTIFY()
+ #endif
+
+ _CORE_message_queue_Set_message_priority( the_message, submit_type );
+
+ #if !defined(RTEMS_SCORE_COREMSG_ENABLE_MESSAGE_PRIORITY)
+ _ISR_Disable( level );
+ SET_NOTIFY();
+ the_message_queue->number_of_pending_messages++;
+ if ( submit_type == CORE_MESSAGE_QUEUE_SEND_REQUEST )
+ _CORE_message_queue_Append_unprotected(the_message_queue, the_message);
+ else
+ _CORE_message_queue_Prepend_unprotected(the_message_queue, the_message);
+ _ISR_Enable( level );
+ #else
+ if ( submit_type == CORE_MESSAGE_QUEUE_SEND_REQUEST ) {
+ _ISR_Disable( level );
+ SET_NOTIFY();
+ the_message_queue->number_of_pending_messages++;
+ _CORE_message_queue_Append_unprotected(the_message_queue, the_message);
+ _ISR_Enable( level );
+ } else if ( submit_type == CORE_MESSAGE_QUEUE_URGENT_REQUEST ) {
+ _ISR_Disable( level );
+ SET_NOTIFY();
+ the_message_queue->number_of_pending_messages++;
+ _CORE_message_queue_Prepend_unprotected(the_message_queue, the_message);
+ _ISR_Enable( level );
+ } else {
+ CORE_message_queue_Buffer_control *this_message;
+ Chain_Node *the_node;
+ Chain_Control *the_header;
+ int the_priority;
+
+ the_priority = _CORE_message_queue_Get_message_priority(the_message);
+ the_header = &the_message_queue->Pending_messages;
+ the_node = _Chain_First( the_header );
+ while ( !_Chain_Is_tail( the_header, the_node ) ) {
+ int this_priority;
+
+ this_message = (CORE_message_queue_Buffer_control *) the_node;
+
+ this_priority = _CORE_message_queue_Get_message_priority(this_message);
+
+ if ( this_priority <= the_priority ) {
+ the_node = the_node->next;
+ continue;
+ }
+ break;
+ }
+ _ISR_Disable( level );
+ SET_NOTIFY();
+ the_message_queue->number_of_pending_messages++;
+ _Chain_Insert_unprotected( the_node->previous, &the_message->Node );
+ _ISR_Enable( level );
+ }
+ #endif
+
+ #if defined(RTEMS_SCORE_COREMSG_ENABLE_NOTIFICATION)
+ /*
+ * According to POSIX, does this happen before or after the message
+ * is actually enqueued. It is logical to think afterwards, because
+ * the message is actually in the queue at this point.
+ */
+ if ( notify && the_message_queue->notify_handler )
+ (*the_message_queue->notify_handler)(the_message_queue->notify_argument);
+ #endif
+}
diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c
new file mode 100644
index 0000000000..9a9fd75567
--- /dev/null
+++ b/cpukit/score/src/coremsgseize.c
@@ -0,0 +1,157 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Seize
+ *
+ * This kernel routine dequeues a message, copies the message buffer to
+ * a given destination buffer, and frees the message buffer to the
+ * inactive message pool. The thread will be blocked if wait is true,
+ * otherwise an error will be given to the thread if no messages are available.
+ *
+ * Input parameters:
+ * the_message_queue - pointer to message queue
+ * id - id of object we are waitig on
+ * buffer - pointer to message buffer to be filled
+ * size_p - pointer to the size of buffer to be filled
+ * wait - true if wait is allowed, false otherwise
+ * timeout - time to wait for a message
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: Dependent on BUFFER_LENGTH
+ *
+ * INTERRUPT LATENCY:
+ * available
+ * wait
+ */
+
+void _CORE_message_queue_Seize(
+ CORE_message_queue_Control *the_message_queue,
+ Objects_Id id,
+ void *buffer,
+ size_t *size_p,
+ bool wait,
+ Watchdog_Interval timeout
+)
+{
+ ISR_Level level;
+ CORE_message_queue_Buffer_control *the_message;
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ _ISR_Disable( level );
+ the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
+ if ( the_message != NULL ) {
+ the_message_queue->number_of_pending_messages -= 1;
+ _ISR_Enable( level );
+
+ *size_p = the_message->Contents.size;
+ _Thread_Executing->Wait.count =
+ _CORE_message_queue_Get_message_priority( the_message );
+ _CORE_message_queue_Copy_buffer(
+ the_message->Contents.buffer,
+ buffer,
+ *size_p
+ );
+
+ #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
+ /*
+ * There is not an API with blocking sends enabled.
+ * So return immediately.
+ */
+ _CORE_message_queue_Free_message_buffer(the_message_queue, the_message);
+ return;
+ #else
+ {
+ Thread_Control *the_thread;
+
+ /*
+ * There could be a thread waiting to send a message. If there
+ * is not, then we can go ahead and free the buffer.
+ *
+ * NOTE: If we note that the queue was not full before this receive,
+ * then we can avoid this dequeue.
+ */
+ the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
+ if ( !the_thread ) {
+ _CORE_message_queue_Free_message_buffer(
+ the_message_queue,
+ the_message
+ );
+ return;
+ }
+
+ /*
+ * There was a thread waiting to send a message. This code
+ * puts the messages in the message queue on behalf of the
+ * waiting task.
+ */
+ _CORE_message_queue_Set_message_priority(
+ the_message,
+ the_thread->Wait.count
+ );
+ the_message->Contents.size = (size_t) the_thread->Wait.option;
+ _CORE_message_queue_Copy_buffer(
+ the_thread->Wait.return_argument_second.immutable_object,
+ the_message->Contents.buffer,
+ the_message->Contents.size
+ );
+
+ _CORE_message_queue_Insert_message(
+ the_message_queue,
+ the_message,
+ _CORE_message_queue_Get_message_priority( the_message )
+ );
+ return;
+ }
+ #endif
+ }
+
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
+ return;
+ }
+
+ _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
+ executing->Wait.queue = &the_message_queue->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.return_argument_second.mutable_object = buffer;
+ executing->Wait.return_argument = size_p;
+ /* Wait.count will be filled in with the message priority */
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
+}
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
new file mode 100644
index 0000000000..c67157dc44
--- /dev/null
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -0,0 +1,180 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _CORE_message_queue_Submit
+ *
+ * This routine implements the send and urgent message functions. It
+ * processes a message that is to be submitted to the designated
+ * message queue. The message will either be processed as a
+ * send message which it will be inserted at the rear of the queue
+ * or it will be processed as an urgent message which will be inserted
+ * at the front of the queue.
+ *
+ * Input parameters:
+ * the_message_queue - message is submitted to this message queue
+ * buffer - pointer to message buffer
+ * size - size in bytes of message to send
+ * id - id of message queue
+ * api_message_queue_mp_support - api specific mp support callout
+ * submit_type - send or urgent message
+ *
+ * Output parameters:
+ * CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+CORE_message_queue_Status _CORE_message_queue_Submit(
+ CORE_message_queue_Control *the_message_queue,
+ const void *buffer,
+ size_t size,
+ Objects_Id id,
+ #if defined(RTEMS_MULTIPROCESSING)
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ #else
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support __attribute__((unused)),
+ #endif
+ CORE_message_queue_Submit_types submit_type,
+ bool wait,
+ Watchdog_Interval timeout
+)
+{
+ CORE_message_queue_Buffer_control *the_message;
+ Thread_Control *the_thread;
+
+ if ( size > the_message_queue->maximum_message_size ) {
+ return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
+ }
+
+ /*
+ * Is there a thread currently waiting on this message queue?
+ */
+ if ( the_message_queue->number_of_pending_messages == 0 ) {
+ the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
+ if ( the_thread ) {
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ the_thread->Wait.return_argument_second.mutable_object,
+ size
+ );
+ *(size_t *) the_thread->Wait.return_argument = size;
+ the_thread->Wait.count = (uint32_t) submit_type;
+
+ #if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_message_queue_mp_support) ( the_thread, id );
+ #endif
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ }
+ }
+
+ /*
+ * No one waiting on the message queue at this time, so attempt to
+ * queue the message up for a future receive.
+ */
+ if ( the_message_queue->number_of_pending_messages <
+ the_message_queue->maximum_pending_messages ) {
+
+ the_message =
+ _CORE_message_queue_Allocate_message_buffer( the_message_queue );
+
+ #if defined(RTEMS_DEBUG)
+ /*
+ * NOTE: If the system is consistent, this error should never occur.
+ */
+
+ if ( !the_message )
+ return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
+ #endif
+
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ the_message->Contents.buffer,
+ size
+ );
+ the_message->Contents.size = size;
+ _CORE_message_queue_Set_message_priority( the_message, submit_type );
+
+ _CORE_message_queue_Insert_message(
+ the_message_queue,
+ the_message,
+ submit_type
+ );
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ }
+
+ #if !defined(RTEMS_SCORE_COREMSG_ENABLE_BLOCKING_SEND)
+ return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
+ #else
+ /*
+ * No message buffers were available so we may need to return an
+ * overflow error or block the sender until the message is placed
+ * on the queue.
+ */
+ if ( !wait ) {
+ return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
+ }
+
+ /*
+ * Do NOT block on a send if the caller is in an ISR. It is
+ * deadly to block in an ISR.
+ */
+ if ( _ISR_Is_in_progress() ) {
+ return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
+ }
+
+ /*
+ * WARNING!! executing should NOT be used prior to this point.
+ * Thus the unusual choice to open a new scope and declare
+ * it as a variable. Doing this emphasizes how dangerous it
+ * would be to use this variable prior to here.
+ */
+ {
+ Thread_Control *executing = _Thread_Executing;
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
+ executing->Wait.queue = &the_message_queue->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.return_argument_second.immutable_object = buffer;
+ executing->Wait.option = (uint32_t) size;
+ executing->Wait.count = submit_type;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
+ }
+
+ return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT;
+ #endif
+}
diff --git a/cpukit/score/src/coremutex.c b/cpukit/score/src/coremutex.c
new file mode 100644
index 0000000000..dcd2e778fe
--- /dev/null
+++ b/cpukit/score/src/coremutex.c
@@ -0,0 +1,94 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_mutex_Initialize
+ *
+ * This routine initializes a mutex at create time and set the control
+ * structure according to the values passed.
+ *
+ * Input parameters:
+ * the_mutex - the mutex control block to initialize
+ * the_mutex_attributes - the mutex attributes specified at create time
+ * initial_lock - mutex initial lock or unlocked status
+ *
+ * Output parameters: NONE
+ */
+
+CORE_mutex_Status _CORE_mutex_Initialize(
+ CORE_mutex_Control *the_mutex,
+ CORE_mutex_Attributes *the_mutex_attributes,
+ uint32_t initial_lock
+)
+{
+
+/* Add this to the RTEMS environment later ?????????
+ rtems_assert( initial_lock == CORE_MUTEX_LOCKED ||
+ initial_lock == CORE_MUTEX_UNLOCKED );
+ */
+
+ the_mutex->Attributes = *the_mutex_attributes;
+ the_mutex->lock = initial_lock;
+ the_mutex->blocked_count = 0;
+
+ if ( initial_lock == CORE_MUTEX_LOCKED ) {
+ the_mutex->nest_count = 1;
+ the_mutex->holder = _Thread_Executing;
+ the_mutex->holder_id = _Thread_Executing->Object.id;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+
+ if ( _Thread_Executing->current_priority <
+ the_mutex->Attributes.priority_ceiling )
+ return CORE_MUTEX_STATUS_CEILING_VIOLATED;
+#ifdef __RTEMS_STRICT_ORDER_MUTEX__
+ _Chain_Prepend_unprotected( &_Thread_Executing->lock_mutex,
+ &the_mutex->queue.lock_queue );
+ the_mutex->queue.priority_before = _Thread_Executing->current_priority;
+#endif
+
+ _Thread_Executing->resource_count++;
+ }
+ } else {
+ the_mutex->nest_count = 0;
+ the_mutex->holder = NULL;
+ the_mutex->holder_id = 0;
+ }
+
+ _Thread_queue_Initialize(
+ &the_mutex->Wait_queue,
+ _CORE_mutex_Is_fifo( the_mutex_attributes ) ?
+ THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY,
+ STATES_WAITING_FOR_MUTEX,
+ CORE_MUTEX_TIMEOUT
+ );
+
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/coremutexflush.c b/cpukit/score/src/coremutexflush.c
new file mode 100644
index 0000000000..2006f2dee8
--- /dev/null
+++ b/cpukit/score/src/coremutexflush.c
@@ -0,0 +1,55 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_mutex_Flush
+ *
+ * This function a flushes the mutex's task wait queue.
+ *
+ * Input parameters:
+ * the_mutex - the mutex to be flushed
+ * remote_extract_callout - function to invoke remotely
+ * status - status to pass to thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_mutex_Flush(
+ CORE_mutex_Control *the_mutex,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+ _Thread_queue_Flush(
+ &the_mutex->Wait_queue,
+ remote_extract_callout,
+ status
+ );
+}
diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c
new file mode 100644
index 0000000000..db6d513cb4
--- /dev/null
+++ b/cpukit/score/src/coremutexseize.c
@@ -0,0 +1,78 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+#if defined(__RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__)
+void _CORE_mutex_Seize(
+ CORE_mutex_Control *_the_mutex,
+ Objects_Id _id,
+ bool _wait,
+ Watchdog_Interval _timeout,
+ ISR_Level _level
+)
+{
+ _CORE_mutex_Seize_body( _the_mutex, _id, _wait, _timeout, _level );
+}
+#endif
+
+/*PAGE
+ *
+ * _CORE_mutex_Seize (interrupt blocking support)
+ *
+ * This routine blocks the caller thread after an attempt attempts to obtain
+ * the specified mutex has failed.
+ *
+ * Input parameters:
+ * the_mutex - pointer to mutex control block
+ * timeout - number of ticks to wait (0 means forever)
+ */
+
+void _CORE_mutex_Seize_interrupt_blocking(
+ CORE_mutex_Control *the_mutex,
+ Watchdog_Interval timeout
+)
+{
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
+ if ( the_mutex->holder->current_priority > executing->current_priority ) {
+ _Thread_Change_priority(
+ the_mutex->holder,
+ executing->current_priority,
+ false
+ );
+ }
+ }
+
+ the_mutex->blocked_count++;
+ _Thread_queue_Enqueue( &the_mutex->Wait_queue, timeout );
+
+ _Thread_Enable_dispatch();
+}
+
diff --git a/cpukit/score/src/coremutexseizeintr.c b/cpukit/score/src/coremutexseizeintr.c
new file mode 100644
index 0000000000..4e4e5c4a07
--- /dev/null
+++ b/cpukit/score/src/coremutexseizeintr.c
@@ -0,0 +1,33 @@
+/*
+ * Mutex Handler -- Seize interrupt disable version
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+#if defined(__RTEMS_DO_NOT_INLINE_CORE_MUTEX_SEIZE__)
+int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+)
+{
+ return _CORE_mutex_Seize_interrupt_trylock_body( the_mutex, level_p );
+}
+#endif
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c
new file mode 100644
index 0000000000..7e1a444215
--- /dev/null
+++ b/cpukit/score/src/coremutexsurrender.c
@@ -0,0 +1,231 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+#ifdef __RTEMS_STRICT_ORDER_MUTEX__
+ static inline void _CORE_mutex_Push_priority(
+ CORE_mutex_Control *mutex,
+ Thread_Control *thread
+ )
+ {
+ _Chain_Prepend_unprotected(
+ &thread->lock_mutex,
+ &mutex->queue.lock_queue
+ );
+ mutex->queue.priority_before = thread->current_priority;
+ }
+
+ static inline CORE_mutex_Status _CORE_mutex_Pop_priority(
+ CORE_mutex_Control *mutex,
+ Thread_Control *holder
+ )
+ {
+ /*
+ * Check whether the holder release the mutex in LIFO order if not return
+ * error code.
+ */
+ if ( _Chain_First( holder->lock_mutex ) != &mutex->queue.lock_queue ) {
+ mutex->nest_count++;
+
+ return CORE_MUTEX_RELEASE_NOT_ORDER;
+ }
+
+ /*
+ * This pops the first node from the list.
+ */
+ _Chain_Get_first_unprotected( &holder->lock_mutex );
+
+ if ( mutex->queue.priority_before != holder->current_priority )
+ _Thread_Change_priority( holder, mutex->queue.priority_before, true );
+
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+ }
+#else
+ #define _CORE_mutex_Push_priority( mutex, thread ) ((void) 0)
+
+ #define _CORE_mutex_Pop_priority( mutex, thread ) \
+ CORE_MUTEX_STATUS_SUCCESSFUL
+#endif
+
+/*
+ * _CORE_mutex_Surrender
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a unit to the mutex. If a task was blocked waiting for
+ * a unit from this mutex, then that task will be readied and the unit
+ * given to that task. Otherwise, the unit will be returned to the mutex.
+ *
+ * Input parameters:
+ * the_mutex - the mutex to be flushed
+ * id - id of parent mutex
+ * api_mutex_mp_support - api dependent MP support actions
+ *
+ * Output parameters:
+ * CORE_MUTEX_STATUS_SUCCESSFUL - if successful
+ * core error code - if unsuccessful
+ */
+
+CORE_mutex_Status _CORE_mutex_Surrender(
+ CORE_mutex_Control *the_mutex,
+#if defined(RTEMS_MULTIPROCESSING)
+ Objects_Id id,
+ CORE_mutex_API_mp_support_callout api_mutex_mp_support
+#else
+ Objects_Id id __attribute__((unused)),
+ CORE_mutex_API_mp_support_callout api_mutex_mp_support __attribute__((unused))
+#endif
+)
+{
+ Thread_Control *the_thread;
+ Thread_Control *holder;
+
+ holder = the_mutex->holder;
+
+ /*
+ * The following code allows a thread (or ISR) other than the thread
+ * which acquired the mutex to release that mutex. This is only
+ * allowed when the mutex in quetion is FIFO or simple Priority
+ * discipline. But Priority Ceiling or Priority Inheritance mutexes
+ * must be released by the thread which acquired them.
+ */
+
+ if ( the_mutex->Attributes.only_owner_release ) {
+ if ( !_Thread_Is_executing( holder ) )
+ return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
+ }
+
+ /* XXX already unlocked -- not right status */
+
+ if ( !the_mutex->nest_count )
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+
+ the_mutex->nest_count--;
+
+ if ( the_mutex->nest_count != 0 ) {
+ /*
+ * All error checking is on the locking side, so if the lock was
+ * allowed to acquired multiple times, then we should just deal with
+ * that. The RTEMS_DEBUG is just a validation.
+ */
+ #if defined(RTEMS_DEBUG)
+ switch ( the_mutex->Attributes.lock_nesting_behavior ) {
+ case CORE_MUTEX_NESTING_ACQUIRES:
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+ #if defined(RTEMS_POSIX_API)
+ case CORE_MUTEX_NESTING_IS_ERROR:
+ /* should never occur */
+ return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
+ #endif
+ case CORE_MUTEX_NESTING_BLOCKS:
+ /* Currently no API exercises this behavior. */
+ break;
+ }
+ #else
+ /* must be CORE_MUTEX_NESTING_ACQUIRES or we wouldn't be here */
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+ #endif
+ }
+
+ /*
+ * Formally release the mutex before possibly transferring it to a
+ * blocked thread.
+ */
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+ CORE_mutex_Status pop_status =
+ _CORE_mutex_Pop_priority( the_mutex, holder );
+
+ if ( pop_status != CORE_MUTEX_STATUS_SUCCESSFUL )
+ return pop_status;
+
+ holder->resource_count--;
+
+ /*
+ * Whether or not someone is waiting for the mutex, an
+ * inherited priority must be lowered if this is the last
+ * mutex (i.e. resource) this task has.
+ */
+ if ( holder->resource_count == 0 &&
+ holder->real_priority != holder->current_priority ) {
+ _Thread_Change_priority( holder, holder->real_priority, true );
+ }
+ }
+ the_mutex->holder = NULL;
+ the_mutex->holder_id = 0;
+
+ /*
+ * Now we check if another thread was waiting for this mutex. If so,
+ * transfer the mutex to that thread.
+ */
+ if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
+
+ the_mutex->holder = NULL;
+ the_mutex->holder_id = the_thread->Object.id;
+ the_mutex->nest_count = 1;
+
+ ( *api_mutex_mp_support)( the_thread, id );
+
+ } else
+#endif
+ {
+
+ the_mutex->holder = the_thread;
+ the_mutex->holder_id = the_thread->Object.id;
+ the_mutex->nest_count = 1;
+
+ switch ( the_mutex->Attributes.discipline ) {
+ case CORE_MUTEX_DISCIPLINES_FIFO:
+ case CORE_MUTEX_DISCIPLINES_PRIORITY:
+ break;
+ case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
+ _CORE_mutex_Push_priority( the_mutex, the_thread );
+ the_thread->resource_count++;
+ break;
+ case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
+ _CORE_mutex_Push_priority( the_mutex, the_thread );
+ the_thread->resource_count++;
+ if (the_mutex->Attributes.priority_ceiling <
+ the_thread->current_priority){
+ _Thread_Change_priority(
+ the_thread,
+ the_mutex->Attributes.priority_ceiling,
+ false
+ );
+ }
+ break;
+ }
+ }
+ } else
+ the_mutex->lock = CORE_MUTEX_UNLOCKED;
+
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/corerwlock.c b/cpukit/score/src/corerwlock.c
new file mode 100644
index 0000000000..7bc988514e
--- /dev/null
+++ b/cpukit/score/src/corerwlock.c
@@ -0,0 +1,61 @@
+/*
+ * SuperCore RWLock Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is part of the implementation of the SuperCore RWLock Handler.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corerwlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_RWLock_Initialize
+ *
+ * This function initialize a rwlock and sets the initial value based
+ * on the given count.
+ *
+ * Input parameters:
+ * the_rwlock - the rwlock control block to initialize
+ * the_rwlock_attributes - the attributes specified at create time
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_RWLock_Initialize(
+ CORE_RWLock_Control *the_rwlock,
+ CORE_RWLock_Attributes *the_rwlock_attributes
+)
+{
+
+ the_rwlock->Attributes = *the_rwlock_attributes;
+/*
+ the_rwlock->number_of_waiting_threads = 0;
+*/
+ the_rwlock->number_of_readers = 0;
+ the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
+
+ _Thread_queue_Initialize(
+ &the_rwlock->Wait_queue,
+ THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_RWLOCK,
+ CORE_RWLOCK_TIMEOUT
+ );
+}
diff --git a/cpukit/score/src/corerwlockobtainread.c b/cpukit/score/src/corerwlockobtainread.c
new file mode 100644
index 0000000000..78b6ebc187
--- /dev/null
+++ b/cpukit/score/src/corerwlockobtainread.c
@@ -0,0 +1,108 @@
+/*
+ * SuperCore RWLock Handler -- Obtain RWLock for reading
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corerwlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _CORE_rwlock_Obtain_for_reading
+ *
+ * This function waits for the rwlock to become available. Optionally,
+ * a limit may be placed on the duration of the spin.
+ *
+ * Input parameters:
+ * the_rwlock - the rwlock control block to initialize
+ * timeout_allowed - true if timeout allowed
+ * timeout - the maximum number of ticks to spin
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_RWLock_Obtain_for_reading(
+ CORE_RWLock_Control *the_rwlock,
+ Objects_Id id,
+ bool wait,
+ Watchdog_Interval timeout,
+ CORE_RWLock_API_mp_support_callout api_rwlock_mp_support
+)
+{
+ ISR_Level level;
+ Thread_Control *executing = _Thread_Executing;
+
+ /*
+ * If unlocked, then OK to read.
+ * If locked for reading and no waiters, then OK to read.
+ * If any thread is waiting, then we wait.
+ */
+
+ _ISR_Disable( level );
+ switch ( the_rwlock->current_state ) {
+ case CORE_RWLOCK_UNLOCKED:
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
+ the_rwlock->number_of_readers += 1;
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ return;
+
+ case CORE_RWLOCK_LOCKED_FOR_READING: {
+ Thread_Control *waiter;
+ waiter = _Thread_queue_First( &the_rwlock->Wait_queue );
+ if ( !waiter ) {
+ the_rwlock->number_of_readers += 1;
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ return;
+ }
+ break;
+ }
+ case CORE_RWLOCK_LOCKED_FOR_WRITING:
+ break;
+ }
+
+ /*
+ * If the thread is not willing to wait, then return immediately.
+ */
+
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
+ return;
+ }
+
+ /*
+ * We need to wait to enter this critical section
+ */
+
+ _Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue );
+ executing->Wait.queue = &the_rwlock->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_READ;
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue_with_handler(
+ &the_rwlock->Wait_queue,
+ timeout,
+ _CORE_RWLock_Timeout
+ );
+
+ /* return to API level so it can dispatch and we block */
+}
diff --git a/cpukit/score/src/corerwlockobtainwrite.c b/cpukit/score/src/corerwlockobtainwrite.c
new file mode 100644
index 0000000000..c3aae6e34c
--- /dev/null
+++ b/cpukit/score/src/corerwlockobtainwrite.c
@@ -0,0 +1,99 @@
+/*
+ * SuperCore RWLock Handler -- Obtain RWLock for writing
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corerwlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _CORE_rwlock_Obtain_for_writing
+ *
+ * This function waits for the rwlock to become available. Optionally,
+ * a limit may be placed on the duration of the spin.
+ *
+ * Input parameters:
+ * the_rwlock - the rwlock control block to initialize
+ * timeout_allowed - true if timeout allowed
+ * timeout - the maximum number of ticks to spin
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_RWLock_Obtain_for_writing(
+ CORE_RWLock_Control *the_rwlock,
+ Objects_Id id,
+ bool wait,
+ Watchdog_Interval timeout,
+ CORE_RWLock_API_mp_support_callout api_rwlock_mp_support
+)
+{
+ ISR_Level level;
+ Thread_Control *executing = _Thread_Executing;
+
+ /*
+ * If unlocked, then OK to read.
+ * Otherwise, we have to block.
+ * If locked for reading and no waiters, then OK to read.
+ * If any thread is waiting, then we wait.
+ */
+
+ _ISR_Disable( level );
+ switch ( the_rwlock->current_state ) {
+ case CORE_RWLOCK_UNLOCKED:
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ return;
+
+ case CORE_RWLOCK_LOCKED_FOR_READING:
+ case CORE_RWLOCK_LOCKED_FOR_WRITING:
+ break;
+ }
+
+ /*
+ * If the thread is not willing to wait, then return immediately.
+ */
+
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
+ return;
+ }
+
+ /*
+ * We need to wait to enter this critical section
+ */
+
+ _Thread_queue_Enter_critical_section( &the_rwlock->Wait_queue );
+ executing->Wait.queue = &the_rwlock->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.option = CORE_RWLOCK_THREAD_WAITING_FOR_WRITE;
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue_with_handler(
+ &the_rwlock->Wait_queue,
+ timeout,
+ _CORE_RWLock_Timeout
+ );
+
+
+ /* return to API level so it can dispatch and we block */
+}
diff --git a/cpukit/score/src/corerwlockrelease.c b/cpukit/score/src/corerwlockrelease.c
new file mode 100644
index 0000000000..379fdebdec
--- /dev/null
+++ b/cpukit/score/src/corerwlockrelease.c
@@ -0,0 +1,106 @@
+/*
+ * SuperCore RWLock Handler -- Release a RWLock
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corerwlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _CORE_RWLock_Release
+ *
+ * This function releases the rwlock.
+ *
+ * Input parameters:
+ * the_rwlock - the rwlock control block to initialize
+ *
+ * Output parameters: NONE
+ */
+
+CORE_RWLock_Status _CORE_RWLock_Release(
+ CORE_RWLock_Control *the_rwlock
+)
+{
+ ISR_Level level;
+ Thread_Control *executing = _Thread_Executing;
+ Thread_Control *next;
+
+ /*
+ * If unlocked, then OK to read.
+ * Otherwise, we have to block.
+ * If locked for reading and no waiters, then OK to read.
+ * If any thread is waiting, then we wait.
+ */
+
+ _ISR_Disable( level );
+ if ( the_rwlock->current_state == CORE_RWLOCK_UNLOCKED){
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_RWLOCK_UNAVAILABLE;
+ return CORE_RWLOCK_SUCCESSFUL;
+ }
+ if ( the_rwlock->current_state == CORE_RWLOCK_LOCKED_FOR_READING ) {
+ the_rwlock->number_of_readers -= 1;
+ if ( the_rwlock->number_of_readers != 0 ) {
+ /* must be unlocked again */
+ _ISR_Enable( level );
+ return CORE_RWLOCK_SUCCESSFUL;
+ }
+ }
+
+ /* CORE_RWLOCK_LOCKED_FOR_WRITING or READING with readers */
+ executing->Wait.return_code = CORE_RWLOCK_SUCCESSFUL;
+
+ /*
+ * Implicitly transition to "unlocked" and find another thread interested
+ * in obtaining this rwlock.
+ */
+ the_rwlock->current_state = CORE_RWLOCK_UNLOCKED;
+ _ISR_Enable( level );
+
+ next = _Thread_queue_Dequeue( &the_rwlock->Wait_queue );
+
+ if ( next ) {
+ if ( next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE ) {
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_WRITING;
+ return CORE_RWLOCK_SUCCESSFUL;
+ }
+
+ /*
+ * Must be CORE_RWLOCK_THREAD_WAITING_FOR_READING
+ */
+ the_rwlock->number_of_readers += 1;
+ the_rwlock->current_state = CORE_RWLOCK_LOCKED_FOR_READING;
+
+ /*
+ * Now see if more readers can be let go.
+ */
+ while ( 1 ) {
+ next = _Thread_queue_First( &the_rwlock->Wait_queue );
+ if ( !next ||
+ next->Wait.option == CORE_RWLOCK_THREAD_WAITING_FOR_WRITE )
+ return CORE_RWLOCK_SUCCESSFUL;
+ the_rwlock->number_of_readers += 1;
+ _Thread_queue_Extract( &the_rwlock->Wait_queue, next );
+ }
+ }
+
+ /* indentation is to match _ISR_Disable at top */
+
+ return CORE_RWLOCK_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/corerwlocktimeout.c b/cpukit/score/src/corerwlocktimeout.c
new file mode 100644
index 0000000000..698b3f8095
--- /dev/null
+++ b/cpukit/score/src/corerwlocktimeout.c
@@ -0,0 +1,55 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corerwlock.h>
+#include <rtems/score/corerwlock.h>
+
+/*
+ * _CORE_RWLock_Timeout
+ *
+ * This routine processes a thread which timeouts while waiting on
+ * a thread queue. It is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_RWLock_Timeout(
+ Objects_Id id,
+ void *ignored
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+#if defined(RTEMS_MULTIPROCESSING)
+ case OBJECTS_REMOTE: /* impossible */
+#endif
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_queue_Process_timeout( the_thread );
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/score/src/coresem.c b/cpukit/score/src/coresem.c
new file mode 100644
index 0000000000..4f5e0720cb
--- /dev/null
+++ b/cpukit/score/src/coresem.c
@@ -0,0 +1,63 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * CORE_semaphore_Initialize
+ *
+ * This function initialize a semaphore and sets the initial value based
+ * on the given count.
+ *
+ * Input parameters:
+ * the_semaphore - the semaphore control block to initialize
+ * the_semaphore_attributes - the attributes specified at create time
+ * initial_value - semaphore's initial value
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_semaphore_Initialize(
+ CORE_semaphore_Control *the_semaphore,
+ CORE_semaphore_Attributes *the_semaphore_attributes,
+ uint32_t initial_value
+)
+{
+
+ the_semaphore->Attributes = *the_semaphore_attributes;
+ the_semaphore->count = initial_value;
+
+ _Thread_queue_Initialize(
+ &the_semaphore->Wait_queue,
+ _CORE_semaphore_Is_priority( the_semaphore_attributes ) ?
+ THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_SEMAPHORE,
+ CORE_SEMAPHORE_TIMEOUT
+ );
+}
diff --git a/cpukit/score/src/coresemflush.c b/cpukit/score/src/coresemflush.c
new file mode 100644
index 0000000000..d4ec72cf22
--- /dev/null
+++ b/cpukit/score/src/coresemflush.c
@@ -0,0 +1,58 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_semaphore_Flush
+ *
+ * This function a flushes the semaphore's task wait queue.
+ *
+ * Input parameters:
+ * the_semaphore - the semaphore to be flushed
+ * remote_extract_callout - function to invoke remotely
+ * status - status to pass to thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_semaphore_Flush(
+ CORE_semaphore_Control *the_semaphore,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+
+ _Thread_queue_Flush(
+ &the_semaphore->Wait_queue,
+ remote_extract_callout,
+ status
+ );
+
+}
diff --git a/cpukit/score/src/coresemseize.c b/cpukit/score/src/coresemseize.c
new file mode 100644
index 0000000000..a66690e148
--- /dev/null
+++ b/cpukit/score/src/coresemseize.c
@@ -0,0 +1,88 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+#if defined(RTEMS_SCORE_CORESEM_ENABLE_SEIZE_BODY)
+/*
+ * This routine attempts to allocate a core semaphore to the calling thread.
+ *
+ * Input parameters:
+ * the_semaphore - pointer to semaphore control block
+ * id - id of object to wait on
+ * wait - true if wait is allowed, false otherwise
+ * timeout - number of ticks to wait (0 means forever)
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * available
+ * wait
+ */
+
+void _CORE_semaphore_Seize(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ bool wait,
+ Watchdog_Interval timeout
+)
+{
+ Thread_Control *executing;
+ ISR_Level level;
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
+ _ISR_Disable( level );
+ if ( the_semaphore->count != 0 ) {
+ the_semaphore->count -= 1;
+ _ISR_Enable( level );
+ return;
+ }
+
+ /*
+ * If the semaphore was not available and the caller was not willing
+ * to block, then return immediately with a status indicating that
+ * the semaphore was not available and the caller never blocked.
+ */
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
+ return;
+ }
+
+ /*
+ * If the semaphore is not available and the caller is willing to
+ * block, then we now block the caller with optional timeout.
+ */
+ _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
+ executing->Wait.queue = &the_semaphore->Wait_queue;
+ executing->Wait.id = id;
+ _ISR_Enable( level );
+ _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
+}
+#endif
diff --git a/cpukit/score/src/coresemsurrender.c b/cpukit/score/src/coresemsurrender.c
new file mode 100644
index 0000000000..321d55e198
--- /dev/null
+++ b/cpukit/score/src/coresemsurrender.c
@@ -0,0 +1,76 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_semaphore_Surrender
+ *
+ * Input parameters:
+ * the_semaphore - the semaphore to be flushed
+ * id - id of parent semaphore
+ * api_semaphore_mp_support - api dependent MP support actions
+ *
+ * Output parameters:
+ * CORE_SEMAPHORE_STATUS_SUCCESSFUL - if successful
+ * core error code - if unsuccessful
+ *
+ * Output parameters:
+ */
+
+CORE_semaphore_Status _CORE_semaphore_Surrender(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
+)
+{
+ Thread_Control *the_thread;
+ ISR_Level level;
+ CORE_semaphore_Status status;
+
+ status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
+
+ if ( (the_thread = _Thread_queue_Dequeue(&the_semaphore->Wait_queue)) ) {
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_semaphore_mp_support) ( the_thread, id );
+#endif
+
+ } else {
+ _ISR_Disable( level );
+ if ( the_semaphore->count < the_semaphore->Attributes.maximum_count )
+ the_semaphore->count += 1;
+ else
+ status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
+ _ISR_Enable( level );
+ }
+
+ return status;
+}
diff --git a/cpukit/score/src/corespinlock.c b/cpukit/score/src/corespinlock.c
new file mode 100644
index 0000000000..5eb3d327c3
--- /dev/null
+++ b/cpukit/score/src/corespinlock.c
@@ -0,0 +1,53 @@
+/*
+ * SuperCore Spinlock Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is part of the implementation of the SuperCore Spinlock Handler.
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corespinlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_spinlock_Initialize
+ *
+ * This function initialize a spinlock and sets the initial value based
+ * on the given count.
+ *
+ * Input parameters:
+ * the_spinlock - the spinlock control block to initialize
+ * the_spinlock_attributes - the attributes specified at create time
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_spinlock_Initialize(
+ CORE_spinlock_Control *the_spinlock,
+ CORE_spinlock_Attributes *the_spinlock_attributes
+)
+{
+
+ the_spinlock->Attributes = *the_spinlock_attributes;
+
+ the_spinlock->lock = 0;
+ the_spinlock->users = 0;
+ the_spinlock->holder = 0;
+}
diff --git a/cpukit/score/src/corespinlockrelease.c b/cpukit/score/src/corespinlockrelease.c
new file mode 100644
index 0000000000..fe027448c1
--- /dev/null
+++ b/cpukit/score/src/corespinlockrelease.c
@@ -0,0 +1,72 @@
+/*
+ * SuperCore Spinlock Handler -- Release a Spinlock
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corespinlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _CORE_spinlock_Release
+ *
+ * This function releases the spinlock.
+ *
+ * Input parameters:
+ * the_spinlock - the spinlock control block to initialize
+ *
+ * Output parameters:
+ * CORE_SPINLOCK_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ *
+ */
+
+CORE_spinlock_Status _CORE_spinlock_Release(
+ CORE_spinlock_Control *the_spinlock
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ /*
+ * It must locked before it can be unlocked.
+ */
+ if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_NOT_LOCKED;
+ }
+
+ /*
+ * It must locked by the current thread before it can be unlocked.
+ */
+ if ( the_spinlock->holder != _Thread_Executing->Object.id ) {
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_NOT_HOLDER;
+ }
+
+ /*
+ * Let it be unlocked.
+ */
+ the_spinlock->users -= 1;
+ the_spinlock->lock = CORE_SPINLOCK_UNLOCKED;
+ the_spinlock->holder = 0;
+
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/corespinlockwait.c b/cpukit/score/src/corespinlockwait.c
new file mode 100644
index 0000000000..cf15163977
--- /dev/null
+++ b/cpukit/score/src/corespinlockwait.c
@@ -0,0 +1,114 @@
+/*
+ * SuperCore Spinlock Handler -- Wait for Spinlock
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/corespinlock.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _CORE_spinlock_Wait
+ *
+ * This function waits for the spinlock to become available. Optionally,
+ * a limit may be placed on the duration of the spin.
+ *
+ * Input parameters:
+ * the_spinlock - the spinlock control block to initialize
+ * wait - true if willing to wait
+ * timeout - the maximum number of ticks to spin (0 is forever)
+ *
+ * Output parameters: NONE
+ */
+
+CORE_spinlock_Status _CORE_spinlock_Wait(
+ CORE_spinlock_Control *the_spinlock,
+ bool wait,
+ Watchdog_Interval timeout
+)
+{
+ ISR_Level level;
+ #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
+ Watchdog_Interval limit = _Watchdog_Ticks_since_boot + timeout;
+ #endif
+
+ _ISR_Disable( level );
+ if ( (the_spinlock->lock == CORE_SPINLOCK_LOCKED) &&
+ (the_spinlock->holder == _Thread_Executing->Object.id) ) {
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_HOLDER_RELOCKING;
+ }
+ the_spinlock->users += 1;
+ for ( ;; ) {
+ if ( the_spinlock->lock == CORE_SPINLOCK_UNLOCKED ) {
+ the_spinlock->lock = CORE_SPINLOCK_LOCKED;
+ the_spinlock->holder = _Thread_Executing->Object.id;
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_SUCCESSFUL;
+ }
+
+ /*
+ * Spinlock is unavailable. If not willing to wait, return.
+ */
+ if ( !wait ) {
+ the_spinlock->users -= 1;
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_UNAVAILABLE;
+ }
+
+ #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
+ /*
+ * They are willing to wait but there could be a timeout.
+ */
+ if ( timeout && (limit <= _Watchdog_Ticks_since_boot) ) {
+ the_spinlock->users -= 1;
+ _ISR_Enable( level );
+ return CORE_SPINLOCK_TIMEOUT;
+ }
+ #endif
+
+ /*
+ * The thread is willing to spin so let's set things up so
+ * another thread has a chance of running. This spinlock has
+ * to be released by either another thread or an ISR. Since
+ * POSIX does not say anything about ISRs, that implies that
+ * another thread must be able to run while spinning. We are
+ * not blocking so that implies we are at least preemptible
+ * and possibly time-sliced.
+ *
+ * So first, we will enable interrpts to allow for them to happen.
+ * Then we will "flash" the thread dispatching critical section
+ * so other threads have a chance to run.
+ *
+ * A spinlock cannot be deleted while it is being used so we are
+ * safe from deletion.
+ */
+
+ _ISR_Enable( level );
+ /* An ISR could occur here */
+
+ _Thread_Enable_dispatch();
+ /* Another thread could get dispatched here */
+
+ /* Reenter the critical sections so we can attempt the lock again. */
+ _Thread_Disable_dispatch();
+
+ _ISR_Disable( level );
+ }
+
+}
diff --git a/cpukit/score/src/coretod.c b/cpukit/score/src/coretod.c
new file mode 100644
index 0000000000..4da8dd4b4f
--- /dev/null
+++ b/cpukit/score/src/coretod.c
@@ -0,0 +1,47 @@
+/*
+ * Time of Day (TOD) Handler
+ */
+
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Handler_initialization
+ *
+ * This routine initializes the time of day handler.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Handler_initialization(void)
+{
+ /* POSIX format TOD (timespec) */
+ _Timestamp_Set( &_TOD_Now, TOD_SECONDS_1970_THROUGH_1988, 0 );
+
+ /* Uptime (timespec) */
+ _Timestamp_Set_to_zero( &_TOD_Uptime );
+
+ /* TOD has not been set */
+ _TOD_Is_set = false;
+ _TOD_Activate();
+}
diff --git a/cpukit/score/src/coretodget.c b/cpukit/score/src/coretodget.c
new file mode 100644
index 0000000000..953f3cb753
--- /dev/null
+++ b/cpukit/score/src/coretodget.c
@@ -0,0 +1,56 @@
+/*
+ * Time of Day (TOD) Handler - get TOD
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/timestamp.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * _TOD_Get
+ *
+ * This routine is used to obtain the current date and time.
+ *
+ * Input parameters:
+ * time - pointer to the time and date structure
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Get(
+ struct timespec *time
+)
+{
+ ISR_Level level;
+ Timestamp_Control offset;
+ Timestamp_Control now;
+ long nanoseconds;
+
+ /* assume time checked for NULL by caller */
+
+ /* _TOD_Now is the native current time */
+ _ISR_Disable( level );
+ now = _TOD_Now;
+ nanoseconds = (*_Watchdog_Nanoseconds_since_tick_handler)();
+ _ISR_Enable( level );
+
+ _Timestamp_Set( &offset, 0, nanoseconds );
+ _Timestamp_Add_to( &now, &offset );
+ _Timestamp_To_timespec( &now, time );
+}
diff --git a/cpukit/score/src/coretodgetuptime.c b/cpukit/score/src/coretodgetuptime.c
new file mode 100644
index 0000000000..c5d940b0c0
--- /dev/null
+++ b/cpukit/score/src/coretodgetuptime.c
@@ -0,0 +1,56 @@
+/*
+ * Time of Day (TOD) Handler - get uptime
+ */
+
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/timestamp.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * _TOD_Get_uptime
+ *
+ * This routine is used to obtain the system uptime
+ *
+ * Input parameters:
+ * time - pointer to the timestamp structure
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Get_uptime(
+ Timestamp_Control *uptime
+)
+{
+ ISR_Level level;
+ Timestamp_Control offset;
+ Timestamp_Control up;
+ long nanoseconds;
+
+ /* assume time checked for NULL by caller */
+
+ /* _TOD_Uptime is in native timestamp format */
+ _ISR_Disable( level );
+ up = _TOD_Uptime;
+ nanoseconds = (*_Watchdog_Nanoseconds_since_tick_handler)();
+ _ISR_Enable( level );
+
+ _Timestamp_Set( &offset, 0, nanoseconds );
+ _Timestamp_Add_to( &up, &offset );
+ *uptime = up;
+}
diff --git a/cpukit/score/src/coretodgetuptimetimespec.c b/cpukit/score/src/coretodgetuptimetimespec.c
new file mode 100644
index 0000000000..6d30a95d9c
--- /dev/null
+++ b/cpukit/score/src/coretodgetuptimetimespec.c
@@ -0,0 +1,44 @@
+/*
+ * Time of Day (TOD) Handler - get uptime
+ */
+
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/timestamp.h>
+#include <rtems/score/tod.h>
+
+/*
+ * _TOD_Get_uptime_as_timespec
+ *
+ * This routine is used to obtain the system uptime
+ *
+ * Input parameters:
+ * time - pointer to the timestamp structure
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Get_uptime_as_timespec(
+ struct timespec *uptime
+)
+{
+ Timestamp_Control uptime_ts;
+
+ /* assume time checked for NULL by caller */
+ _TOD_Get_uptime( &uptime_ts );
+ _Timestamp_To_timespec( &uptime_ts, uptime );
+}
diff --git a/cpukit/score/src/coretodmsecstoticks.c b/cpukit/score/src/coretodmsecstoticks.c
new file mode 100644
index 0000000000..cddd3d646d
--- /dev/null
+++ b/cpukit/score/src/coretodmsecstoticks.c
@@ -0,0 +1,25 @@
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/tod.h>
+
+uint32_t TOD_MILLISECONDS_TO_TICKS(
+ uint32_t milliseconds
+)
+{
+ return (milliseconds / rtems_configuration_get_milliseconds_per_tick());
+}
diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c
new file mode 100644
index 0000000000..9329fd7d8f
--- /dev/null
+++ b/cpukit/score/src/coretodset.c
@@ -0,0 +1,62 @@
+/*
+ * Time of Day (TOD) Handler -- Set Time
+ */
+
+/* COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/timestamp.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Set
+ *
+ * This rountine sets the current date and time with the specified
+ * new date and time structure.
+ *
+ * Input parameters:
+ * time - pointer to the time and date structure
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Set(
+ const struct timespec *time
+)
+{
+ long seconds;
+
+ _Thread_Disable_dispatch();
+ _TOD_Deactivate();
+
+ seconds = _TOD_Seconds_since_epoch();
+
+ if ( time->tv_sec < seconds )
+ _Watchdog_Adjust_seconds( WATCHDOG_BACKWARD, seconds - time->tv_sec );
+ else
+ _Watchdog_Adjust_seconds( WATCHDOG_FORWARD, time->tv_sec - seconds );
+
+ /* POSIX format TOD (timespec) */
+ _Timestamp_Set( &_TOD_Now, time->tv_sec, time->tv_nsec );
+ _TOD_Is_set = true;
+
+ _TOD_Activate();
+
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/score/src/coretodtickle.c b/cpukit/score/src/coretodtickle.c
new file mode 100644
index 0000000000..ddc8e4aac0
--- /dev/null
+++ b/cpukit/score/src/coretodtickle.c
@@ -0,0 +1,60 @@
+/*
+ * Time of Day (TOD) Handler -- Tickle Ticks
+ */
+
+/* COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/timestamp.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/config.h>
+
+/*PAGE
+ *
+ * _TOD_Tickle_ticks
+ *
+ * This routine processes a clock tick.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Tickle_ticks( void )
+{
+ Timestamp_Control tick;
+ uint32_t seconds;
+
+ /* Convert the tick quantum to a timestamp */
+ _Timestamp_Set( &tick, 0, rtems_configuration_get_nanoseconds_per_tick() );
+
+ /* Update the counter of ticks since boot */
+ _Watchdog_Ticks_since_boot += 1;
+
+ /* Update the timespec format uptime */
+ _Timestamp_Add_to( &_TOD_Uptime, &tick );
+ /* we do not care how much the uptime changed */
+
+ /* Update the timespec format TOD */
+ seconds = _Timestamp_Add_to_at_tick( &_TOD_Now, &tick );
+ while ( seconds ) {
+ _Watchdog_Tickle_seconds();
+ seconds--;
+ }
+}
+
diff --git a/cpukit/score/src/coretodtickspersec.c b/cpukit/score/src/coretodtickspersec.c
new file mode 100644
index 0000000000..ac6316ba7b
--- /dev/null
+++ b/cpukit/score/src/coretodtickspersec.c
@@ -0,0 +1,24 @@
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/tod.h>
+
+uint32_t TOD_TICKS_PER_SECOND_method(void)
+{
+ return (TOD_MICROSECONDS_PER_SECOND /
+ rtems_configuration_get_microseconds_per_tick());
+}
diff --git a/cpukit/score/src/coretodusectoticks.c b/cpukit/score/src/coretodusectoticks.c
new file mode 100644
index 0000000000..be2cbd7024
--- /dev/null
+++ b/cpukit/score/src/coretodusectoticks.c
@@ -0,0 +1,25 @@
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/tod.h>
+
+uint32_t TOD_MICROSECONDS_TO_TICKS(
+ uint32_t microseconds
+)
+{
+ return (microseconds / rtems_configuration_get_microseconds_per_tick());
+}
diff --git a/cpukit/score/src/heap.c b/cpukit/score/src/heap.c
new file mode 100644
index 0000000000..b972d84c3c
--- /dev/null
+++ b/cpukit/score/src/heap.c
@@ -0,0 +1,488 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2009, 2010 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/heap.h>
+#include <rtems/score/interr.h>
+
+#if CPU_ALIGNMENT == 0 || CPU_ALIGNMENT % 2 != 0
+ #error "invalid CPU_ALIGNMENT value"
+#endif
+
+static uint32_t instance = 0;
+
+/*PAGE
+ *
+ * _Heap_Initialize
+ *
+ * This kernel routine initializes a heap.
+ *
+ * Input parameters:
+ * heap - pointer to heap header
+ * area_begin - starting address of heap
+ * size - size of heap
+ * page_size - allocatable unit of memory
+ *
+ * Output parameters:
+ * returns - maximum memory available if RTEMS_SUCCESSFUL
+ * 0 - otherwise
+ *
+ * This is what a heap looks like in memory immediately after initialization:
+ *
+ *
+ * +--------------------------------+ <- begin = area_begin
+ * | unused space due to alignment |
+ * | size < page_size |
+ * 0 +--------------------------------+ <- first block
+ * | prev_size = page_size |
+ * 4 +--------------------------------+
+ * | size = size0 | 1 |
+ * 8 +---------------------+----------+ <- aligned on page_size
+ * | next = HEAP_TAIL | |
+ * 12 +---------------------+ |
+ * | prev = HEAP_HEAD | memory |
+ * +---------------------+ |
+ * | available |
+ * | |
+ * | for allocation |
+ * | |
+ * size0 +--------------------------------+ <- last dummy block
+ * | prev_size = size0 |
+ * +4 +--------------------------------+
+ * | size = page_size | 0 | <- prev block is free
+ * +8 +--------------------------------+ <- aligned on page_size
+ * | unused space due to alignment |
+ * | size < page_size |
+ * +--------------------------------+ <- end = begin + size
+ *
+ * Below is what a heap looks like after first allocation of SIZE bytes using
+ * _Heap_allocate(). BSIZE stands for SIZE + 4 aligned up on 'page_size'
+ * boundary.
+ * [NOTE: If allocation were performed by _Heap_Allocate_aligned(), the
+ * block size BSIZE is defined differently, and previously free block will
+ * be split so that upper part of it will become used block (see
+ * 'heapallocatealigned.c' for details).]
+ *
+ * +--------------------------------+ <- begin = area_begin
+ * | unused space due to alignment |
+ * | size < page_size |
+ * 0 +--------------------------------+ <- used block
+ * | prev_size = page_size |
+ * 4 +--------------------------------+
+ * | size = BSIZE | 1 | <- prev block is used
+ * 8 +--------------------------------+ <- aligned on page_size
+ * | . | Pointer returned to the user
+ * | . | is 8 for _Heap_Allocate()
+ * | . | and is in range
+ * 8 + | user-accessible | [8,8+page_size) for
+ * page_size +- - - - - -+ _Heap_Allocate_aligned()
+ * | area |
+ * | . |
+ * BSIZE +- - - - - . - - - - -+ <- free block
+ * | . |
+ * BSIZE +4 +--------------------------------+
+ * | size = S = size0 - BSIZE | 1 | <- prev block is used
+ * BSIZE +8 +-------------------+------------+ <- aligned on page_size
+ * | next = HEAP_TAIL | |
+ * BSIZE +12 +-------------------+ |
+ * | prev = HEAP_HEAD | memory |
+ * +-------------------+ |
+ * | . available |
+ * | . |
+ * | . for |
+ * | . |
+ * BSIZE +S+0 +-------------------+ allocation + <- last dummy block
+ * | prev_size = S | |
+ * +S+4 +-------------------+------------+
+ * | size = page_size | 0 | <- prev block is free
+ * +S+8 +--------------------------------+ <- aligned on page_size
+ * | unused space due to alignment |
+ * | size < page_size |
+ * +--------------------------------+ <- end = begin + size
+ *
+ */
+
+#ifdef HEAP_PROTECTION
+ static void _Heap_Protection_block_initialize_default(
+ Heap_Control *heap,
+ Heap_Block *block
+ )
+ {
+ block->Protection_begin.protector [0] = HEAP_BEGIN_PROTECTOR_0;
+ block->Protection_begin.protector [1] = HEAP_BEGIN_PROTECTOR_1;
+ block->Protection_begin.next_delayed_free_block = NULL;
+ block->Protection_begin.task = _Thread_Executing;
+ block->Protection_begin.tag = NULL;
+ block->Protection_end.protector [0] = HEAP_END_PROTECTOR_0;
+ block->Protection_end.protector [1] = HEAP_END_PROTECTOR_1;
+ }
+
+ static void _Heap_Protection_block_check_default(
+ Heap_Control *heap,
+ Heap_Block *block
+ )
+ {
+ if (
+ block->Protection_begin.protector [0] != HEAP_BEGIN_PROTECTOR_0
+ || block->Protection_begin.protector [1] != HEAP_BEGIN_PROTECTOR_1
+ || block->Protection_end.protector [0] != HEAP_END_PROTECTOR_0
+ || block->Protection_end.protector [1] != HEAP_END_PROTECTOR_1
+ ) {
+ _Heap_Protection_block_error( heap, block );
+ }
+ }
+
+ static void _Heap_Protection_block_error_default(
+ Heap_Control *heap,
+ Heap_Block *block
+ )
+ {
+ /* FIXME */
+ _Internal_error_Occurred( 0xdeadbeef, false, 0xdeadbeef );
+ }
+#endif
+
+bool _Heap_Get_first_and_last_block(
+ uintptr_t heap_area_begin,
+ uintptr_t heap_area_size,
+ uintptr_t page_size,
+ uintptr_t min_block_size,
+ Heap_Block **first_block_ptr,
+ Heap_Block **last_block_ptr
+)
+{
+ uintptr_t const heap_area_end = heap_area_begin + heap_area_size;
+ uintptr_t const alloc_area_begin =
+ _Heap_Align_up( heap_area_begin + HEAP_BLOCK_HEADER_SIZE, page_size );
+ uintptr_t const first_block_begin =
+ alloc_area_begin - HEAP_BLOCK_HEADER_SIZE;
+ uintptr_t const overhead =
+ HEAP_BLOCK_HEADER_SIZE + (first_block_begin - heap_area_begin);
+ uintptr_t const first_block_size =
+ _Heap_Align_down( heap_area_size - overhead, page_size );
+ Heap_Block *const first_block = (Heap_Block *) first_block_begin;
+ Heap_Block *const last_block =
+ _Heap_Block_at( first_block, first_block_size );
+
+ if (
+ heap_area_end < heap_area_begin
+ || heap_area_size <= overhead
+ || first_block_size < min_block_size
+ ) {
+ /* Invalid area or area too small */
+ return false;
+ }
+
+ *first_block_ptr = first_block;
+ *last_block_ptr = last_block;
+
+ return true;
+}
+
+uintptr_t _Heap_Initialize(
+ Heap_Control *heap,
+ void *heap_area_begin_ptr,
+ uintptr_t heap_area_size,
+ uintptr_t page_size
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+ uintptr_t const heap_area_begin = (uintptr_t) heap_area_begin_ptr;
+ uintptr_t const heap_area_end = heap_area_begin + heap_area_size;
+ uintptr_t first_block_begin = 0;
+ uintptr_t first_block_size = 0;
+ uintptr_t last_block_begin = 0;
+ uintptr_t min_block_size = 0;
+ bool area_ok = false;
+ Heap_Block *first_block = NULL;
+ Heap_Block *last_block = NULL;
+
+ if ( page_size == 0 ) {
+ page_size = CPU_ALIGNMENT;
+ } else {
+ page_size = _Heap_Align_up( page_size, CPU_ALIGNMENT );
+
+ if ( page_size < CPU_ALIGNMENT ) {
+ /* Integer overflow */
+ return 0;
+ }
+ }
+ min_block_size = _Heap_Align_up( sizeof( Heap_Block ), page_size );
+
+ area_ok = _Heap_Get_first_and_last_block(
+ heap_area_begin,
+ heap_area_size,
+ page_size,
+ min_block_size,
+ &first_block,
+ &last_block
+ );
+ if ( !area_ok ) {
+ return 0;
+ }
+
+ memset(heap, 0, sizeof(*heap));
+
+ #ifdef HEAP_PROTECTION
+ heap->Protection.block_initialize = _Heap_Protection_block_initialize_default;
+ heap->Protection.block_check = _Heap_Protection_block_check_default;
+ heap->Protection.block_error = _Heap_Protection_block_error_default;
+ #endif
+
+ first_block_begin = (uintptr_t) first_block;
+ last_block_begin = (uintptr_t) last_block;
+ first_block_size = last_block_begin - first_block_begin;
+
+ /* First block */
+ first_block->prev_size = heap_area_end;
+ first_block->size_and_flag = first_block_size | HEAP_PREV_BLOCK_USED;
+ first_block->next = _Heap_Free_list_tail( heap );
+ first_block->prev = _Heap_Free_list_head( heap );
+ _Heap_Protection_block_initialize( heap, first_block );
+
+ /* Heap control */
+ heap->page_size = page_size;
+ heap->min_block_size = min_block_size;
+ heap->area_begin = heap_area_begin;
+ heap->area_end = heap_area_end;
+ heap->first_block = first_block;
+ heap->last_block = last_block;
+ _Heap_Free_list_head( heap )->next = first_block;
+ _Heap_Free_list_tail( heap )->prev = first_block;
+
+ /* Last block */
+ last_block->prev_size = first_block_size;
+ last_block->size_and_flag = 0;
+ _Heap_Set_last_block_size( heap );
+ _Heap_Protection_block_initialize( heap, last_block );
+
+ /* Statistics */
+ stats->size = first_block_size;
+ stats->free_size = first_block_size;
+ stats->min_free_size = first_block_size;
+ stats->free_blocks = 1;
+ stats->max_free_blocks = 1;
+ stats->instance = instance++;
+
+ _HAssert( _Heap_Is_aligned( heap->page_size, CPU_ALIGNMENT ) );
+ _HAssert( _Heap_Is_aligned( heap->min_block_size, page_size ) );
+ _HAssert(
+ _Heap_Is_aligned( _Heap_Alloc_area_of_block( first_block ), page_size )
+ );
+ _HAssert(
+ _Heap_Is_aligned( _Heap_Alloc_area_of_block( last_block ), page_size )
+ );
+
+ return first_block_size;
+}
+
+static void _Heap_Block_split(
+ Heap_Control *heap,
+ Heap_Block *block,
+ Heap_Block *free_list_anchor,
+ uintptr_t alloc_size
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const min_block_size = heap->min_block_size;
+ uintptr_t const min_alloc_size = min_block_size - HEAP_BLOCK_HEADER_SIZE;
+
+ uintptr_t const block_size = _Heap_Block_size( block );
+
+ uintptr_t const used_size =
+ _Heap_Max( alloc_size, min_alloc_size ) + HEAP_BLOCK_HEADER_SIZE;
+ uintptr_t const used_block_size = _Heap_Align_up( used_size, page_size );
+
+ uintptr_t const free_size = block_size + HEAP_ALLOC_BONUS - used_size;
+ uintptr_t const free_size_limit = min_block_size + HEAP_ALLOC_BONUS;
+
+ Heap_Block *next_block = _Heap_Block_at( block, block_size );
+
+ _HAssert( used_size <= block_size + HEAP_ALLOC_BONUS );
+ _HAssert( used_size + free_size == block_size + HEAP_ALLOC_BONUS );
+
+ if ( free_size >= free_size_limit ) {
+ Heap_Block *const free_block = _Heap_Block_at( block, used_block_size );
+ uintptr_t free_block_size = block_size - used_block_size;
+
+ _HAssert( used_block_size + free_block_size == block_size );
+
+ _Heap_Block_set_size( block, used_block_size );
+
+ /* Statistics */
+ stats->free_size += free_block_size;
+
+ if ( _Heap_Is_used( next_block ) ) {
+ _Heap_Free_list_insert_after( free_list_anchor, free_block );
+
+ /* Statistics */
+ ++stats->free_blocks;
+ } else {
+ uintptr_t const next_block_size = _Heap_Block_size( next_block );
+
+ _Heap_Free_list_replace( next_block, free_block );
+
+ free_block_size += next_block_size;
+
+ next_block = _Heap_Block_at( free_block, free_block_size );
+ }
+
+ free_block->size_and_flag = free_block_size | HEAP_PREV_BLOCK_USED;
+
+ next_block->prev_size = free_block_size;
+ next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
+
+ _Heap_Protection_block_initialize( heap, free_block );
+ } else {
+ next_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
+ }
+}
+
+static Heap_Block *_Heap_Block_allocate_from_begin(
+ Heap_Control *heap,
+ Heap_Block *block,
+ Heap_Block *free_list_anchor,
+ uintptr_t alloc_size
+)
+{
+ _Heap_Block_split( heap, block, free_list_anchor, alloc_size );
+
+ return block;
+}
+
+static Heap_Block *_Heap_Block_allocate_from_end(
+ Heap_Control *heap,
+ Heap_Block *block,
+ Heap_Block *free_list_anchor,
+ uintptr_t alloc_begin,
+ uintptr_t alloc_size
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+
+ uintptr_t block_begin = (uintptr_t) block;
+ uintptr_t block_size = _Heap_Block_size( block );
+ uintptr_t block_end = block_begin + block_size;
+
+ Heap_Block *const new_block =
+ _Heap_Block_of_alloc_area( alloc_begin, heap->page_size );
+ uintptr_t const new_block_begin = (uintptr_t) new_block;
+ uintptr_t const new_block_size = block_end - new_block_begin;
+
+ block_end = new_block_begin;
+ block_size = block_end - block_begin;
+
+ _HAssert( block_size >= heap->min_block_size );
+ _HAssert( new_block_size >= heap->min_block_size );
+
+ /* Statistics */
+ stats->free_size += block_size;
+
+ if ( _Heap_Is_prev_used( block ) ) {
+ _Heap_Free_list_insert_after( free_list_anchor, block );
+
+ free_list_anchor = block;
+
+ /* Statistics */
+ ++stats->free_blocks;
+ } else {
+ Heap_Block *const prev_block = _Heap_Prev_block( block );
+ uintptr_t const prev_block_size = _Heap_Block_size( prev_block );
+
+ block = prev_block;
+ block_size += prev_block_size;
+ }
+
+ block->size_and_flag = block_size | HEAP_PREV_BLOCK_USED;
+
+ new_block->prev_size = block_size;
+ new_block->size_and_flag = new_block_size;
+
+ _Heap_Block_split( heap, new_block, free_list_anchor, alloc_size );
+
+ return new_block;
+}
+
+Heap_Block *_Heap_Block_allocate(
+ Heap_Control *heap,
+ Heap_Block *block,
+ uintptr_t alloc_begin,
+ uintptr_t alloc_size
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+
+ uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block( block );
+ uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
+
+ Heap_Block *free_list_anchor = NULL;
+
+ _HAssert( alloc_area_begin <= alloc_begin );
+
+ if ( _Heap_Is_free( block ) ) {
+ free_list_anchor = block->prev;
+
+ _Heap_Free_list_remove( block );
+
+ /* Statistics */
+ --stats->free_blocks;
+ ++stats->used_blocks;
+ stats->free_size -= _Heap_Block_size( block );
+ } else {
+ free_list_anchor = _Heap_Free_list_head( heap );
+ }
+
+ if ( alloc_area_offset < heap->page_size ) {
+ alloc_size += alloc_area_offset;
+
+ block = _Heap_Block_allocate_from_begin(
+ heap,
+ block,
+ free_list_anchor,
+ alloc_size
+ );
+ } else {
+ block = _Heap_Block_allocate_from_end(
+ heap,
+ block,
+ free_list_anchor,
+ alloc_begin,
+ alloc_size
+ );
+ }
+
+ /* Statistics */
+ if ( stats->min_free_size > stats->free_size ) {
+ stats->min_free_size = stats->free_size;
+ }
+
+ _Heap_Protection_block_initialize( heap, block );
+
+ return block;
+}
diff --git a/cpukit/score/src/heapallocate.c b/cpukit/score/src/heapallocate.c
new file mode 100644
index 0000000000..61cebc2054
--- /dev/null
+++ b/cpukit/score/src/heapallocate.c
@@ -0,0 +1,280 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+#ifndef HEAP_PROTECTION
+ #define _Heap_Protection_free_delayed_blocks( heap, alloc_begin ) false
+#else
+ static bool _Heap_Protection_free_delayed_blocks(
+ Heap_Control *heap,
+ uintptr_t alloc_begin
+ )
+ {
+ bool search_again = false;
+ uintptr_t const blocks_to_free_count =
+ (heap->Protection.delayed_free_block_count + 1) / 2;
+
+ if ( alloc_begin == 0 && blocks_to_free_count > 0 ) {
+ Heap_Block *block_to_free = heap->Protection.first_delayed_free_block;
+ uintptr_t count = 0;
+
+ for ( count = 0; count < blocks_to_free_count; ++count ) {
+ Heap_Block *next_block_to_free =
+ block_to_free->Protection_begin.next_delayed_free_block;
+
+ block_to_free->Protection_begin.next_delayed_free_block =
+ HEAP_PROTECTION_OBOLUS;
+
+ _Heap_Free(
+ heap,
+ (void *) _Heap_Alloc_area_of_block( block_to_free )
+ );
+
+ block_to_free = next_block_to_free;
+ }
+
+ heap->Protection.delayed_free_block_count -= blocks_to_free_count;
+ heap->Protection.first_delayed_free_block = block_to_free;
+
+ search_again = true;
+ }
+
+ return search_again;
+ }
+#endif
+
+#ifdef RTEMS_HEAP_DEBUG
+ static void _Heap_Check_allocation(
+ const Heap_Control *heap,
+ const Heap_Block *block,
+ uintptr_t alloc_begin,
+ uintptr_t alloc_size,
+ uintptr_t alignment,
+ uintptr_t boundary
+ )
+ {
+ uintptr_t const min_block_size = heap->min_block_size;
+ uintptr_t const page_size = heap->page_size;
+
+ uintptr_t const block_begin = (uintptr_t) block;
+ uintptr_t const block_size = _Heap_Block_size( block );
+ uintptr_t const block_end = block_begin + block_size;
+
+ uintptr_t const alloc_end = alloc_begin + alloc_size;
+
+ uintptr_t const alloc_area_begin = _Heap_Alloc_area_of_block( block );
+ uintptr_t const alloc_area_offset = alloc_begin - alloc_area_begin;
+
+ _HAssert( block_size >= min_block_size );
+ _HAssert( block_begin < block_end );
+ _HAssert(
+ _Heap_Is_aligned( block_begin + HEAP_BLOCK_HEADER_SIZE, page_size )
+ );
+ _HAssert(
+ _Heap_Is_aligned( block_size, page_size )
+ );
+
+ _HAssert( alloc_end <= block_end + HEAP_ALLOC_BONUS );
+ _HAssert( alloc_area_begin == block_begin + HEAP_BLOCK_HEADER_SIZE);
+ _HAssert( alloc_area_offset < page_size );
+
+ _HAssert( _Heap_Is_aligned( alloc_area_begin, page_size ) );
+ if ( alignment == 0 ) {
+ _HAssert( alloc_begin == alloc_area_begin );
+ } else {
+ _HAssert( _Heap_Is_aligned( alloc_begin, alignment ) );
+ }
+
+ if ( boundary != 0 ) {
+ uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
+
+ _HAssert( alloc_size <= boundary );
+ _HAssert( boundary_line <= alloc_begin || alloc_end <= boundary_line );
+ }
+ }
+#else
+ #define _Heap_Check_allocation( h, b, ab, as, ag, bd ) ((void) 0)
+#endif
+
+static uintptr_t _Heap_Check_block(
+ const Heap_Control *heap,
+ const Heap_Block *block,
+ uintptr_t alloc_size,
+ uintptr_t alignment,
+ uintptr_t boundary
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const min_block_size = heap->min_block_size;
+
+ uintptr_t const block_begin = (uintptr_t) block;
+ uintptr_t const block_size = _Heap_Block_size( block );
+ uintptr_t const block_end = block_begin + block_size;
+
+ uintptr_t const alloc_begin_floor = _Heap_Alloc_area_of_block( block );
+ uintptr_t const alloc_begin_ceiling = block_end - min_block_size
+ + HEAP_BLOCK_HEADER_SIZE + page_size - 1;
+
+ uintptr_t alloc_end = block_end + HEAP_ALLOC_BONUS;
+ uintptr_t alloc_begin = alloc_end - alloc_size;
+
+ alloc_begin = _Heap_Align_down( alloc_begin, alignment );
+
+ /* Ensure that the we have a valid new block at the end */
+ if ( alloc_begin > alloc_begin_ceiling ) {
+ alloc_begin = _Heap_Align_down( alloc_begin_ceiling, alignment );
+ }
+
+ alloc_end = alloc_begin + alloc_size;
+
+ /* Ensure boundary constaint */
+ if ( boundary != 0 ) {
+ uintptr_t const boundary_floor = alloc_begin_floor + alloc_size;
+ uintptr_t boundary_line = _Heap_Align_down( alloc_end, boundary );
+
+ while ( alloc_begin < boundary_line && boundary_line < alloc_end ) {
+ if ( boundary_line < boundary_floor ) {
+ return 0;
+ }
+ alloc_begin = boundary_line - alloc_size;
+ alloc_begin = _Heap_Align_down( alloc_begin, alignment );
+ alloc_end = alloc_begin + alloc_size;
+ boundary_line = _Heap_Align_down( alloc_end, boundary );
+ }
+ }
+
+ /* Ensure that the we have a valid new block at the beginning */
+ if ( alloc_begin >= alloc_begin_floor ) {
+ uintptr_t const alloc_block_begin =
+ (uintptr_t) _Heap_Block_of_alloc_area( alloc_begin, page_size );
+ uintptr_t const free_size = alloc_block_begin - block_begin;
+
+ if ( free_size >= min_block_size || free_size == 0 ) {
+ return alloc_begin;
+ }
+ }
+
+ return 0;
+}
+
+void *_Heap_Allocate_aligned_with_boundary(
+ Heap_Control *heap,
+ uintptr_t alloc_size,
+ uintptr_t alignment,
+ uintptr_t boundary
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+ uintptr_t const block_size_floor = alloc_size + HEAP_BLOCK_HEADER_SIZE
+ - HEAP_ALLOC_BONUS;
+ uintptr_t const page_size = heap->page_size;
+ Heap_Block *block = NULL;
+ uintptr_t alloc_begin = 0;
+ uint32_t search_count = 0;
+ bool search_again = false;
+
+ if ( block_size_floor < alloc_size ) {
+ /* Integer overflow occured */
+ return NULL;
+ }
+
+ if ( boundary != 0 ) {
+ if ( boundary < alloc_size ) {
+ return NULL;
+ }
+
+ if ( alignment == 0 ) {
+ alignment = page_size;
+ }
+ }
+
+ do {
+ Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
+
+ block = _Heap_Free_list_first( heap );
+ while ( block != free_list_tail ) {
+ _HAssert( _Heap_Is_prev_used( block ) );
+
+ _Heap_Protection_block_check( heap, block );
+
+ /*
+ * The HEAP_PREV_BLOCK_USED flag is always set in the block size_and_flag
+ * field. Thus the value is about one unit larger than the real block
+ * size. The greater than operator takes this into account.
+ */
+ if ( block->size_and_flag > block_size_floor ) {
+ if ( alignment == 0 ) {
+ alloc_begin = _Heap_Alloc_area_of_block( block );
+ } else {
+ alloc_begin = _Heap_Check_block(
+ heap,
+ block,
+ alloc_size,
+ alignment,
+ boundary
+ );
+ }
+ }
+
+ /* Statistics */
+ ++search_count;
+
+ if ( alloc_begin != 0 ) {
+ break;
+ }
+
+ block = block->next;
+ }
+
+ search_again = _Heap_Protection_free_delayed_blocks( heap, alloc_begin );
+ } while ( search_again );
+
+ if ( alloc_begin != 0 ) {
+ /* Statistics */
+ ++stats->allocs;
+ stats->searches += search_count;
+
+ block = _Heap_Block_allocate( heap, block, alloc_begin, alloc_size );
+
+ _Heap_Check_allocation(
+ heap,
+ block,
+ alloc_begin,
+ alloc_size,
+ alignment,
+ boundary
+ );
+ }
+
+ /* Statistics */
+ if ( stats->max_search < search_count ) {
+ stats->max_search = search_count;
+ }
+
+ return (void *) alloc_begin;
+}
diff --git a/cpukit/score/src/heapextend.c b/cpukit/score/src/heapextend.c
new file mode 100644
index 0000000000..eab2a9482d
--- /dev/null
+++ b/cpukit/score/src/heapextend.c
@@ -0,0 +1,243 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2010 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+static void _Heap_Free_block( Heap_Control *heap, Heap_Block *block )
+{
+ Heap_Statistics *const stats = &heap->stats;
+
+ /* Statistics */
+ ++stats->used_blocks;
+ --stats->frees;
+
+ _Heap_Free( heap, (void *) _Heap_Alloc_area_of_block( block ));
+}
+
+static void _Heap_Merge_below(
+ Heap_Control *heap,
+ uintptr_t extend_area_begin,
+ Heap_Block *first_block
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const new_first_block_alloc_begin =
+ _Heap_Align_up( extend_area_begin + HEAP_BLOCK_HEADER_SIZE, page_size );
+ uintptr_t const new_first_block_begin =
+ new_first_block_alloc_begin - HEAP_BLOCK_HEADER_SIZE;
+ uintptr_t const first_block_begin = (uintptr_t) first_block;
+ uintptr_t const new_first_block_size =
+ first_block_begin - new_first_block_begin;
+ Heap_Block *const new_first_block = (Heap_Block *) new_first_block_begin;
+
+ new_first_block->prev_size = first_block->prev_size;
+ new_first_block->size_and_flag = new_first_block_size | HEAP_PREV_BLOCK_USED;
+
+ _Heap_Free_block( heap, new_first_block );
+}
+
+static void _Heap_Merge_above(
+ Heap_Control *heap,
+ Heap_Block *last_block,
+ uintptr_t extend_area_end
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const last_block_begin = (uintptr_t) last_block;
+ uintptr_t const last_block_new_size = _Heap_Align_down(
+ extend_area_end - last_block_begin - HEAP_BLOCK_HEADER_SIZE,
+ page_size
+ );
+ Heap_Block *const new_last_block =
+ _Heap_Block_at( last_block, last_block_new_size );
+
+ new_last_block->size_and_flag =
+ (last_block->size_and_flag - last_block_new_size)
+ | HEAP_PREV_BLOCK_USED;
+
+ _Heap_Block_set_size( last_block, last_block_new_size );
+
+ _Heap_Free_block( heap, last_block );
+}
+
+static void _Heap_Link_below(
+ Heap_Block *link,
+ Heap_Block *last_block
+)
+{
+ uintptr_t const last_block_begin = (uintptr_t) last_block;
+ uintptr_t const link_begin = (uintptr_t) link;
+
+ last_block->size_and_flag =
+ (link_begin - last_block_begin) | HEAP_PREV_BLOCK_USED;
+}
+
+static void _Heap_Link_above(
+ Heap_Block *link,
+ Heap_Block *first_block,
+ Heap_Block *last_block
+)
+{
+ uintptr_t const link_begin = (uintptr_t) link;
+ uintptr_t const first_block_begin = (uintptr_t) first_block;
+
+ _Heap_Block_set_size( link, first_block_begin - link_begin );
+
+ last_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
+}
+
+bool _Heap_Extend(
+ Heap_Control *heap,
+ void *extend_area_begin_ptr,
+ uintptr_t extend_area_size,
+ uintptr_t *extended_size_ptr
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+ Heap_Block *const first_block = heap->first_block;
+ Heap_Block *start_block = first_block;
+ Heap_Block *merge_below_block = NULL;
+ Heap_Block *merge_above_block = NULL;
+ Heap_Block *link_below_block = NULL;
+ Heap_Block *link_above_block = NULL;
+ Heap_Block *extend_first_block = NULL;
+ Heap_Block *extend_last_block = NULL;
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const min_block_size = heap->min_block_size;
+ uintptr_t const extend_area_begin = (uintptr_t) extend_area_begin_ptr;
+ uintptr_t const extend_area_end = extend_area_begin + extend_area_size;
+ uintptr_t const free_size = stats->free_size;
+ uintptr_t extend_first_block_size = 0;
+ uintptr_t extended_size = 0;
+ bool extend_area_ok = false;
+
+ if ( extend_area_end < extend_area_begin ) {
+ return false;
+ }
+
+ extend_area_ok = _Heap_Get_first_and_last_block(
+ extend_area_begin,
+ extend_area_size,
+ page_size,
+ min_block_size,
+ &extend_first_block,
+ &extend_last_block
+ );
+ if (!extend_area_ok ) {
+ /* For simplicity we reject extend areas that are too small */
+ return false;
+ }
+
+ do {
+ uintptr_t const sub_area_begin = (start_block != first_block) ?
+ (uintptr_t) start_block : heap->area_begin;
+ uintptr_t const sub_area_end = start_block->prev_size;
+ Heap_Block *const end_block =
+ _Heap_Block_of_alloc_area( sub_area_end, page_size );
+
+ if (
+ sub_area_end > extend_area_begin && extend_area_end > sub_area_begin
+ ) {
+ return false;
+ }
+
+ if ( extend_area_end == sub_area_begin ) {
+ merge_below_block = start_block;
+ } else if ( extend_area_end < sub_area_end ) {
+ link_below_block = start_block;
+ }
+
+ if ( sub_area_end == extend_area_begin ) {
+ start_block->prev_size = extend_area_end;
+
+ merge_above_block = end_block;
+ } else if ( sub_area_end < extend_area_begin ) {
+ link_above_block = end_block;
+ }
+
+ start_block = _Heap_Block_at( end_block, _Heap_Block_size( end_block ) );
+ } while ( start_block != first_block );
+
+ if ( extend_area_begin < heap->area_begin ) {
+ heap->area_begin = extend_area_begin;
+ } else if ( heap->area_end < extend_area_end ) {
+ heap->area_end = extend_area_end;
+ }
+
+ extend_first_block_size =
+ (uintptr_t) extend_last_block - (uintptr_t) extend_first_block;
+
+ extend_first_block->prev_size = extend_area_end;
+ extend_first_block->size_and_flag =
+ extend_first_block_size | HEAP_PREV_BLOCK_USED;
+ _Heap_Protection_block_initialize( heap, extend_first_block );
+
+ extend_last_block->prev_size = extend_first_block_size;
+ extend_last_block->size_and_flag = 0;
+ _Heap_Protection_block_initialize( heap, extend_last_block );
+
+ if ( (uintptr_t) extend_first_block < (uintptr_t) heap->first_block ) {
+ heap->first_block = extend_first_block;
+ } else if ( (uintptr_t) extend_last_block > (uintptr_t) heap->last_block ) {
+ heap->last_block = extend_last_block;
+ }
+
+ if ( merge_below_block != NULL ) {
+ _Heap_Merge_below( heap, extend_area_begin, merge_below_block );
+ } else if ( link_below_block != NULL ) {
+ _Heap_Link_below(
+ link_below_block,
+ extend_last_block
+ );
+ }
+
+ if ( merge_above_block != NULL ) {
+ _Heap_Merge_above( heap, merge_above_block, extend_area_end );
+ } else if ( link_above_block != NULL ) {
+ _Heap_Link_above(
+ link_above_block,
+ extend_first_block,
+ extend_last_block
+ );
+ }
+
+ if ( merge_below_block == NULL && merge_above_block == NULL ) {
+ _Heap_Free_block( heap, extend_first_block );
+ }
+
+ _Heap_Set_last_block_size( heap );
+
+ extended_size = stats->free_size - free_size;
+
+ /* Statistics */
+ stats->size += extended_size;
+
+ if ( extended_size_ptr != NULL )
+ *extended_size_ptr = extended_size;
+
+ return true;
+}
diff --git a/cpukit/score/src/heapfree.c b/cpukit/score/src/heapfree.c
new file mode 100644
index 0000000000..25a1e6964d
--- /dev/null
+++ b/cpukit/score/src/heapfree.c
@@ -0,0 +1,215 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/heap.h>
+
+#ifndef HEAP_PROTECTION
+ #define _Heap_Protection_determine_block_free( heap, block ) true
+#else
+ static void _Heap_Protection_delay_block_free(
+ Heap_Control *heap,
+ Heap_Block *block
+ )
+ {
+ uintptr_t *const pattern_begin = (uintptr_t *)
+ _Heap_Alloc_area_of_block( block );
+ uintptr_t *const pattern_end = (uintptr_t *)
+ ((uintptr_t) block + _Heap_Block_size( block ) + HEAP_ALLOC_BONUS);
+ uintptr_t const delayed_free_block_count =
+ heap->Protection.delayed_free_block_count;
+ uintptr_t *current = NULL;
+
+ block->Protection_begin.next_delayed_free_block = block;
+ block->Protection_begin.task = _Thread_Executing;
+
+ if ( delayed_free_block_count > 0 ) {
+ Heap_Block *const last = heap->Protection.last_delayed_free_block;
+
+ last->Protection_begin.next_delayed_free_block = block;
+ } else {
+ heap->Protection.first_delayed_free_block = block;
+ }
+ heap->Protection.last_delayed_free_block = block;
+ heap->Protection.delayed_free_block_count = delayed_free_block_count + 1;
+
+ for ( current = pattern_begin; current != pattern_end; ++current ) {
+ *current = HEAP_FREE_PATTERN;
+ }
+ }
+
+ static void _Heap_Protection_check_free_block(
+ Heap_Control *heap,
+ Heap_Block *block
+ )
+ {
+ uintptr_t *const pattern_begin = (uintptr_t *)
+ _Heap_Alloc_area_of_block( block );
+ uintptr_t *const pattern_end = (uintptr_t *)
+ ((uintptr_t) block + _Heap_Block_size( block ) + HEAP_ALLOC_BONUS);
+ uintptr_t *current = NULL;
+
+ for ( current = pattern_begin; current != pattern_end; ++current ) {
+ if ( *current != HEAP_FREE_PATTERN ) {
+ _Heap_Protection_block_error( heap, block );
+ break;
+ }
+ }
+ }
+
+ static bool _Heap_Protection_determine_block_free(
+ Heap_Control *heap,
+ Heap_Block *block
+ )
+ {
+ bool do_free = true;
+
+ /*
+ * Sometimes after a free the allocated area is still in use. An example
+ * is the task stack of a thread that deletes itself. The thread dispatch
+ * disable level is a way to detect this use case.
+ */
+ if ( _Thread_Dispatch_disable_level == 0 ) {
+ Heap_Block *const next = block->Protection_begin.next_delayed_free_block;
+ if ( next == NULL ) {
+ _Heap_Protection_delay_block_free( heap, block );
+ do_free = false;
+ } else if ( next == HEAP_PROTECTION_OBOLUS ) {
+ _Heap_Protection_check_free_block( heap, block );
+ } else {
+ _Heap_Protection_block_error( heap, block );
+ }
+ }
+
+ return do_free;
+ }
+#endif
+
+bool _Heap_Free( Heap_Control *heap, void *alloc_begin_ptr )
+{
+ Heap_Statistics *const stats = &heap->stats;
+ uintptr_t alloc_begin;
+ Heap_Block *block;
+ Heap_Block *next_block = NULL;
+ uintptr_t block_size = 0;
+ uintptr_t next_block_size = 0;
+ bool next_is_free = false;
+
+ /*
+ * If NULL return true so a free on NULL is considered a valid release. This
+ * is a special case that could be handled by the in heap check how-ever that
+ * would result in false being returned which is wrong.
+ */
+ if ( alloc_begin_ptr == NULL ) {
+ return true;
+ }
+
+ alloc_begin = (uintptr_t) alloc_begin_ptr;
+ block = _Heap_Block_of_alloc_area( alloc_begin, heap->page_size );
+
+ if ( !_Heap_Is_block_in_heap( heap, block ) ) {
+ return false;
+ }
+
+ _Heap_Protection_block_check( heap, block );
+
+ block_size = _Heap_Block_size( block );
+ next_block = _Heap_Block_at( block, block_size );
+
+ if ( !_Heap_Is_block_in_heap( heap, next_block ) ) {
+ return false;
+ }
+
+ _Heap_Protection_block_check( heap, next_block );
+
+ if ( !_Heap_Is_prev_used( next_block ) ) {
+ _Heap_Protection_block_error( heap, block );
+ return false;
+ }
+
+ if ( !_Heap_Protection_determine_block_free( heap, block ) ) {
+ return true;
+ }
+
+ next_block_size = _Heap_Block_size( next_block );
+ next_is_free = next_block != heap->last_block
+ && !_Heap_Is_prev_used( _Heap_Block_at( next_block, next_block_size ));
+
+ if ( !_Heap_Is_prev_used( block ) ) {
+ uintptr_t const prev_size = block->prev_size;
+ Heap_Block * const prev_block = _Heap_Block_at( block, -prev_size );
+
+ if ( !_Heap_Is_block_in_heap( heap, prev_block ) ) {
+ _HAssert( false );
+ return( false );
+ }
+
+ /* As we always coalesce free blocks, the block that preceedes prev_block
+ must have been used. */
+ if ( !_Heap_Is_prev_used ( prev_block) ) {
+ _HAssert( false );
+ return( false );
+ }
+
+ if ( next_is_free ) { /* coalesce both */
+ uintptr_t const size = block_size + prev_size + next_block_size;
+ _Heap_Free_list_remove( next_block );
+ stats->free_blocks -= 1;
+ prev_block->size_and_flag = size | HEAP_PREV_BLOCK_USED;
+ next_block = _Heap_Block_at( prev_block, size );
+ _HAssert(!_Heap_Is_prev_used( next_block));
+ next_block->prev_size = size;
+ } else { /* coalesce prev */
+ uintptr_t const size = block_size + prev_size;
+ prev_block->size_and_flag = size | HEAP_PREV_BLOCK_USED;
+ next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
+ next_block->prev_size = size;
+ }
+ } else if ( next_is_free ) { /* coalesce next */
+ uintptr_t const size = block_size + next_block_size;
+ _Heap_Free_list_replace( next_block, block );
+ block->size_and_flag = size | HEAP_PREV_BLOCK_USED;
+ next_block = _Heap_Block_at( block, size );
+ next_block->prev_size = size;
+ } else { /* no coalesce */
+ /* Add 'block' to the head of the free blocks list as it tends to
+ produce less fragmentation than adding to the tail. */
+ _Heap_Free_list_insert_after( _Heap_Free_list_head( heap), block );
+ block->size_and_flag = block_size | HEAP_PREV_BLOCK_USED;
+ next_block->size_and_flag &= ~HEAP_PREV_BLOCK_USED;
+ next_block->prev_size = block_size;
+
+ /* Statistics */
+ ++stats->free_blocks;
+ if ( stats->max_free_blocks < stats->free_blocks ) {
+ stats->max_free_blocks = stats->free_blocks;
+ }
+ }
+
+ /* Statistics */
+ --stats->used_blocks;
+ ++stats->frees;
+ stats->free_size += block_size;
+
+ return( true );
+}
diff --git a/cpukit/score/src/heapgetfreeinfo.c b/cpukit/score/src/heapgetfreeinfo.c
new file mode 100644
index 0000000000..406ed81d39
--- /dev/null
+++ b/cpukit/score/src/heapgetfreeinfo.c
@@ -0,0 +1,54 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2004.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+void _Heap_Get_free_information(
+ Heap_Control *the_heap,
+ Heap_Information *info
+)
+{
+ Heap_Block *the_block;
+ Heap_Block *const tail = _Heap_Free_list_tail(the_heap);
+
+ info->number = 0;
+ info->largest = 0;
+ info->total = 0;
+
+ for(the_block = _Heap_Free_list_first(the_heap);
+ the_block != tail;
+ the_block = the_block->next)
+ {
+ uint32_t const the_size = _Heap_Block_size(the_block);
+
+ /* As we always coalesce free blocks, prev block must have been used. */
+ _HAssert(_Heap_Is_prev_used(the_block));
+
+ info->number++;
+ info->total += the_size;
+ if ( info->largest < the_size )
+ info->largest = the_size;
+ }
+}
diff --git a/cpukit/score/src/heapgetinfo.c b/cpukit/score/src/heapgetinfo.c
new file mode 100644
index 0000000000..bcb5a7f68d
--- /dev/null
+++ b/cpukit/score/src/heapgetinfo.c
@@ -0,0 +1,57 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+void _Heap_Get_information(
+ Heap_Control *the_heap,
+ Heap_Information_block *the_info
+)
+{
+ Heap_Block *the_block = the_heap->first_block;
+ Heap_Block *const end = the_heap->last_block;
+
+ memset(the_info, 0, sizeof(*the_info));
+
+ while ( the_block != end ) {
+ uintptr_t const the_size = _Heap_Block_size(the_block);
+ Heap_Block *const next_block = _Heap_Block_at(the_block, the_size);
+ Heap_Information *info;
+
+ if ( _Heap_Is_prev_used(next_block) )
+ info = &the_info->Used;
+ else
+ info = &the_info->Free;
+
+ info->number++;
+ info->total += the_size;
+ if ( info->largest < the_size )
+ info->largest = the_size;
+
+ the_block = next_block;
+ }
+}
diff --git a/cpukit/score/src/heapresizeblock.c b/cpukit/score/src/heapresizeblock.c
new file mode 100644
index 0000000000..2d3528645f
--- /dev/null
+++ b/cpukit/score/src/heapresizeblock.c
@@ -0,0 +1,119 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * Copyright (c) 2009 embedded brains GmbH.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+static Heap_Resize_status _Heap_Resize_block_checked(
+ Heap_Control *heap,
+ Heap_Block *block,
+ uintptr_t alloc_begin,
+ uintptr_t new_alloc_size,
+ uintptr_t *old_size,
+ uintptr_t *new_size
+)
+{
+ Heap_Statistics *const stats = &heap->stats;
+
+ uintptr_t const block_begin = (uintptr_t) block;
+ uintptr_t block_size = _Heap_Block_size( block );
+ uintptr_t block_end = block_begin + block_size;
+
+ uintptr_t alloc_size = block_end - alloc_begin + HEAP_ALLOC_BONUS;
+
+ Heap_Block *next_block = _Heap_Block_at( block, block_size );
+ uintptr_t next_block_size = _Heap_Block_size( next_block );
+ bool next_block_is_free = _Heap_Is_free( next_block );;
+
+ _HAssert( _Heap_Is_block_in_heap( heap, next_block ) );
+ _HAssert( _Heap_Is_prev_used( next_block ) );
+
+ *old_size = alloc_size;
+
+ if ( next_block_is_free ) {
+ block_size += next_block_size;
+ alloc_size += next_block_size;
+ }
+
+ if ( new_alloc_size > alloc_size ) {
+ return HEAP_RESIZE_UNSATISFIED;
+ }
+
+ if ( next_block_is_free ) {
+ _Heap_Block_set_size( block, block_size );
+
+ _Heap_Free_list_remove( next_block );
+
+ next_block = _Heap_Block_at( block, block_size );
+ next_block->size_and_flag |= HEAP_PREV_BLOCK_USED;
+
+ /* Statistics */
+ --stats->free_blocks;
+ stats->free_size -= next_block_size;
+ }
+
+ block = _Heap_Block_allocate( heap, block, alloc_begin, new_alloc_size );
+
+ block_size = _Heap_Block_size( block );
+ next_block = _Heap_Block_at( block, block_size );
+ *new_size = (uintptr_t) next_block - alloc_begin + HEAP_ALLOC_BONUS;
+
+ /* Statistics */
+ ++stats->resizes;
+
+ return HEAP_RESIZE_SUCCESSFUL;
+}
+
+Heap_Resize_status _Heap_Resize_block(
+ Heap_Control *heap,
+ void *alloc_begin_ptr,
+ uintptr_t new_alloc_size,
+ uintptr_t *old_size,
+ uintptr_t *new_size
+)
+{
+ uintptr_t const page_size = heap->page_size;
+
+ uintptr_t const alloc_begin = (uintptr_t) alloc_begin_ptr;
+
+ Heap_Block *const block = _Heap_Block_of_alloc_area( alloc_begin, page_size );
+
+ *old_size = 0;
+ *new_size = 0;
+
+ if ( _Heap_Is_block_in_heap( heap, block ) ) {
+ _Heap_Protection_block_check( heap, block );
+ return _Heap_Resize_block_checked(
+ heap,
+ block,
+ alloc_begin,
+ new_alloc_size,
+ old_size,
+ new_size
+ );
+ }
+ return HEAP_RESIZE_FATAL_ERROR;
+}
diff --git a/cpukit/score/src/heapsizeofuserarea.c b/cpukit/score/src/heapsizeofuserarea.c
new file mode 100644
index 0000000000..0a8b150811
--- /dev/null
+++ b/cpukit/score/src/heapsizeofuserarea.c
@@ -0,0 +1,58 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+bool _Heap_Size_of_alloc_area(
+ Heap_Control *heap,
+ void *alloc_begin_ptr,
+ uintptr_t *alloc_size
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const alloc_begin = (uintptr_t) alloc_begin_ptr;
+ Heap_Block *block = _Heap_Block_of_alloc_area( alloc_begin, page_size );
+ Heap_Block *next_block = NULL;
+ uintptr_t block_size = 0;
+
+ if ( !_Heap_Is_block_in_heap( heap, block ) ) {
+ return false;
+ }
+
+ block_size = _Heap_Block_size( block );
+ next_block = _Heap_Block_at( block, block_size );
+
+ if (
+ !_Heap_Is_block_in_heap( heap, next_block )
+ || !_Heap_Is_prev_used( next_block )
+ ) {
+ return false;
+ }
+
+ *alloc_size = (uintptr_t) next_block + HEAP_ALLOC_BONUS - alloc_begin;
+
+ return true;
+}
+
diff --git a/cpukit/score/src/heapwalk.c b/cpukit/score/src/heapwalk.c
new file mode 100644
index 0000000000..fae0bd6330
--- /dev/null
+++ b/cpukit/score/src/heapwalk.c
@@ -0,0 +1,421 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreHeap
+ *
+ * @brief Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT ( c ) 1989-2007.
+ * On-Line Applications Research Corporation ( OAR ).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+#include <rtems/score/interr.h>
+#include <rtems/bspIo.h>
+
+typedef void (*Heap_Walk_printer)(int, bool, const char*, ...);
+
+static void _Heap_Walk_print_nothing(
+ int source,
+ bool error,
+ const char *fmt,
+ ...
+)
+{
+ /* Do nothing */
+}
+
+static void _Heap_Walk_print( int source, bool error, const char *fmt, ... )
+{
+ va_list ap;
+
+ if ( error ) {
+ printk( "FAIL[%d]: ", source );
+ } else {
+ printk( "PASS[%d]: ", source );
+ }
+
+ va_start( ap, fmt );
+ vprintk( fmt, ap );
+ va_end( ap );
+}
+
+static bool _Heap_Walk_check_free_list(
+ int source,
+ Heap_Walk_printer printer,
+ Heap_Control *heap
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
+ const Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
+ const Heap_Block *prev_block = free_list_tail;
+ const Heap_Block *free_block = first_free_block;
+
+ while ( free_block != free_list_tail ) {
+ if ( !_Heap_Is_block_in_heap( heap, free_block ) ) {
+ (*printer)(
+ source,
+ true,
+ "free block 0x%08x: not in heap\n",
+ free_block
+ );
+
+ return false;
+ }
+
+ if (
+ !_Heap_Is_aligned( _Heap_Alloc_area_of_block( free_block ), page_size )
+ ) {
+ (*printer)(
+ source,
+ true,
+ "free block 0x%08x: alloc area not page aligned\n",
+ free_block
+ );
+
+ return false;
+ }
+
+ if ( _Heap_Is_used( free_block ) ) {
+ (*printer)(
+ source,
+ true,
+ "free block 0x%08x: is used\n",
+ free_block
+ );
+
+ return false;
+ }
+
+ if ( free_block->prev != prev_block ) {
+ (*printer)(
+ source,
+ true,
+ "free block 0x%08x: invalid previous block 0x%08x\n",
+ free_block,
+ free_block->prev
+ );
+
+ return false;
+ }
+
+ prev_block = free_block;
+ free_block = free_block->next;
+ }
+
+ return true;
+}
+
+static bool _Heap_Walk_is_in_free_list(
+ Heap_Control *heap,
+ Heap_Block *block
+)
+{
+ const Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
+ const Heap_Block *free_block = _Heap_Free_list_first( heap );
+
+ while ( free_block != free_list_tail ) {
+ if ( free_block == block ) {
+ return true;
+ }
+ free_block = free_block->next;
+ }
+
+ return false;
+}
+
+static bool _Heap_Walk_check_control(
+ int source,
+ Heap_Walk_printer printer,
+ Heap_Control *heap
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const min_block_size = heap->min_block_size;
+ Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
+ Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
+ Heap_Block *const first_block = heap->first_block;
+ Heap_Block *const last_block = heap->last_block;
+
+ (*printer)(
+ source,
+ false,
+ "page size %u, min block size %u\n"
+ "\tarea begin 0x%08x, area end 0x%08x\n"
+ "\tfirst block 0x%08x, last block 0x%08x\n"
+ "\tfirst free 0x%08x, last free 0x%08x\n",
+ page_size, min_block_size,
+ heap->area_begin, heap->area_end,
+ first_block, last_block,
+ first_free_block, last_free_block
+ );
+
+ if ( page_size == 0 ) {
+ (*printer)( source, true, "page size is zero\n" );
+
+ return false;
+ }
+
+ if ( !_Addresses_Is_aligned( (void *) page_size ) ) {
+ (*printer)(
+ source,
+ true,
+ "page size %u not CPU aligned\n",
+ page_size
+ );
+
+ return false;
+ }
+
+ if ( !_Heap_Is_aligned( min_block_size, page_size ) ) {
+ (*printer)(
+ source,
+ true,
+ "min block size %u not page aligned\n",
+ min_block_size
+ );
+
+ return false;
+ }
+
+ if (
+ !_Heap_Is_aligned( _Heap_Alloc_area_of_block( first_block ), page_size )
+ ) {
+ (*printer)(
+ source,
+ true,
+ "first block 0x%08x: alloc area not page aligned\n",
+ first_block
+ );
+
+ return false;
+ }
+
+ if ( !_Heap_Is_prev_used( first_block ) ) {
+ (*printer)(
+ source,
+ true,
+ "first block: HEAP_PREV_BLOCK_USED is cleared\n"
+ );
+
+ return false;
+ }
+
+ if ( _Heap_Is_free( last_block ) ) {
+ (*printer)(
+ source,
+ true,
+ "last block: is free\n"
+ );
+
+ return false;
+ }
+
+ if (
+ _Heap_Block_at( last_block, _Heap_Block_size( last_block ) ) != first_block
+ ) {
+ (*printer)(
+ source,
+ true,
+ "last block: next block is not the first block\n"
+ );
+
+ return false;
+ }
+
+ return _Heap_Walk_check_free_list( source, printer, heap );
+}
+
+static bool _Heap_Walk_check_free_block(
+ int source,
+ Heap_Walk_printer printer,
+ Heap_Control *heap,
+ Heap_Block *block
+)
+{
+ Heap_Block *const free_list_tail = _Heap_Free_list_tail( heap );
+ Heap_Block *const free_list_head = _Heap_Free_list_head( heap );
+ Heap_Block *const first_free_block = _Heap_Free_list_first( heap );
+ Heap_Block *const last_free_block = _Heap_Free_list_last( heap );
+ bool const prev_used = _Heap_Is_prev_used( block );
+ uintptr_t const block_size = _Heap_Block_size( block );
+ Heap_Block *const next_block = _Heap_Block_at( block, block_size );
+
+ (*printer)(
+ source,
+ false,
+ "block 0x%08x: size %u, prev 0x%08x%s, next 0x%08x%s\n",
+ block,
+ block_size,
+ block->prev,
+ block->prev == first_free_block ?
+ " (= first free)"
+ : (block->prev == free_list_head ? " (= head)" : ""),
+ block->next,
+ block->next == last_free_block ?
+ " (= last free)"
+ : (block->next == free_list_tail ? " (= tail)" : "")
+ );
+
+ if ( block_size != next_block->prev_size ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: size %u != size %u (in next block 0x%08x)\n",
+ block,
+ block_size,
+ next_block->prev_size,
+ next_block
+ );
+
+ return false;
+ }
+
+ if ( !prev_used ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: two consecutive blocks are free\n",
+ block
+ );
+
+ return false;
+ }
+
+ if ( !_Heap_Walk_is_in_free_list( heap, block ) ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: free block not in free list\n",
+ block
+ );
+
+ return false;
+ }
+
+ return true;
+}
+
+bool _Heap_Walk(
+ Heap_Control *heap,
+ int source,
+ bool dump
+)
+{
+ uintptr_t const page_size = heap->page_size;
+ uintptr_t const min_block_size = heap->min_block_size;
+ Heap_Block *const first_block = heap->first_block;
+ Heap_Block *const last_block = heap->last_block;
+ Heap_Block *block = first_block;
+ Heap_Walk_printer printer = dump ?
+ _Heap_Walk_print : _Heap_Walk_print_nothing;
+
+ if ( !_System_state_Is_up( _System_state_Get() ) ) {
+ return true;
+ }
+
+ if ( !_Heap_Walk_check_control( source, printer, heap ) ) {
+ return false;
+ }
+
+ do {
+ uintptr_t const block_begin = (uintptr_t) block;
+ uintptr_t const block_size = _Heap_Block_size( block );
+ bool const prev_used = _Heap_Is_prev_used( block );
+ Heap_Block *const next_block = _Heap_Block_at( block, block_size );
+ uintptr_t const next_block_begin = (uintptr_t) next_block;
+ bool const is_not_last_block = block != last_block;
+
+ if ( !_Heap_Is_block_in_heap( heap, next_block ) ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: next block 0x%08x not in heap\n",
+ block,
+ next_block
+ );
+
+ return false;
+ }
+
+ if ( !_Heap_Is_aligned( block_size, page_size ) && is_not_last_block ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: block size %u not page aligned\n",
+ block,
+ block_size
+ );
+
+ return false;
+ }
+
+ if ( block_size < min_block_size && is_not_last_block ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: size %u < min block size %u\n",
+ block,
+ block_size,
+ min_block_size
+ );
+
+ return false;
+ }
+
+ if ( next_block_begin <= block_begin && is_not_last_block ) {
+ (*printer)(
+ source,
+ true,
+ "block 0x%08x: next block 0x%08x is not a successor\n",
+ block,
+ next_block
+ );
+
+ return false;
+ }
+
+ if ( !_Heap_Is_prev_used( next_block ) ) {
+ if ( !_Heap_Walk_check_free_block( source, printer, heap, block ) ) {
+ return false;
+ }
+ } else if (prev_used) {
+ (*printer)(
+ source,
+ false,
+ "block 0x%08x: size %u\n",
+ block,
+ block_size
+ );
+ } else {
+ (*printer)(
+ source,
+ false,
+ "block 0x%08x: size %u, prev_size %u\n",
+ block,
+ block_size,
+ block->prev_size
+ );
+ }
+
+ block = next_block;
+ } while ( block != first_block );
+
+ return true;
+}
diff --git a/cpukit/score/src/interr.c b/cpukit/score/src/interr.c
new file mode 100644
index 0000000000..cd9e09121e
--- /dev/null
+++ b/cpukit/score/src/interr.c
@@ -0,0 +1,65 @@
+/*
+ * Internal Error Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/userext.h>
+
+/*PAGE
+ *
+ * _Internal_error_Occurred
+ *
+ * This routine will invoke the fatal error handler supplied by the user
+ * followed by the the default one provided by the executive. The default
+ * error handler assumes no hardware is present to help inform the user
+ * of the problem. Halt stores the error code in a known register,
+ * disables interrupts, and halts the CPU. If the CPU does not have a
+ * halt instruction, it will loop to itself.
+ *
+ * Input parameters:
+ * the_source - what subsystem the error originated in
+ * is_internal - if the error was internally generated
+ * the_error - fatal error status code
+ *
+ * Output parameters:
+ * As much information as possible is stored in a CPU dependent fashion.
+ * See the CPU dependent code for more information.
+ *
+ * NOTE: The the_error is not necessarily a directive status code.
+ */
+
+void _Internal_error_Occurred(
+ Internal_errors_Source the_source,
+ bool is_internal,
+ Internal_errors_t the_error
+)
+{
+
+ _Internal_errors_What_happened.the_source = the_source;
+ _Internal_errors_What_happened.is_internal = is_internal;
+ _Internal_errors_What_happened.the_error = the_error;
+
+ _User_extensions_Fatal( the_source, is_internal, the_error );
+
+ _System_state_Set( SYSTEM_STATE_FAILED );
+
+ _CPU_Fatal_halt( the_error );
+
+ /* will not return from this routine */
+ while (true);
+}
diff --git a/cpukit/score/src/isr.c b/cpukit/score/src/isr.c
new file mode 100644
index 0000000000..799bb08dbb
--- /dev/null
+++ b/cpukit/score/src/isr.c
@@ -0,0 +1,83 @@
+/*
+ * ISR Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/config.h>
+
+/* _ISR_Handler_initialization
+ *
+ * This routine initializes the ISR handler.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _ISR_Handler_initialization( void )
+{
+ _ISR_Nest_level = 0;
+
+#if (CPU_SIMPLE_VECTORED_INTERRUPTS == TRUE)
+ _ISR_Vector_table = _Workspace_Allocate_or_fatal_error(
+ sizeof(ISR_Handler_entry) * ISR_NUMBER_OF_VECTORS
+ );
+#endif
+
+ _CPU_Initialize_vectors();
+
+#if ( CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
+
+ if ( !_Stack_Is_enough(Configuration.interrupt_stack_size) )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL
+ );
+
+ _CPU_Interrupt_stack_low = _Workspace_Allocate_or_fatal_error(
+ Configuration.interrupt_stack_size
+ );
+
+ _CPU_Interrupt_stack_high = _Addresses_Add_offset(
+ _CPU_Interrupt_stack_low,
+ Configuration.interrupt_stack_size
+ );
+
+#if (CPU_STACK_ALIGNMENT != 0)
+ _CPU_Interrupt_stack_high = (void *)
+ ((uintptr_t) _CPU_Interrupt_stack_high & ~(CPU_STACK_ALIGNMENT - 1));
+#endif
+
+ /* Interrupt stack might have to be aligned and/or setup
+ * in a specific way.
+ */
+#if defined(_CPU_Interrupt_stack_setup)
+ _CPU_Interrupt_stack_setup(_CPU_Interrupt_stack_low, _CPU_Interrupt_stack_high);
+#endif
+
+#endif
+
+#if ( CPU_HAS_HARDWARE_INTERRUPT_STACK == TRUE )
+ _CPU_Install_interrupt_stack();
+#endif
+
+}
diff --git a/cpukit/score/src/iterateoverthreads.c b/cpukit/score/src/iterateoverthreads.c
new file mode 100644
index 0000000000..8c65becc4c
--- /dev/null
+++ b/cpukit/score/src/iterateoverthreads.c
@@ -0,0 +1,55 @@
+/*
+ * rtems_iterate_over_all_threads
+ *
+ * This function operates by as follows:
+ * for all threads
+ * invoke specified function
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+
+void rtems_iterate_over_all_threads(rtems_per_thread_routine routine)
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+
+ if ( !routine )
+ return;
+
+ for ( api_index = 1 ; api_index <= OBJECTS_APIS_LAST ; api_index++ ) {
+ #if !defined(RTEMS_POSIX_API) || defined(RTEMS_DEBUG)
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ #endif
+
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( !information )
+ continue;
+
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( !the_thread )
+ continue;
+
+ (*routine)(the_thread);
+ }
+ }
+
+}
diff --git a/cpukit/score/src/mpci.c b/cpukit/score/src/mpci.c
new file mode 100644
index 0000000000..d8f68ebc89
--- /dev/null
+++ b/cpukit/score/src/mpci.c
@@ -0,0 +1,540 @@
+/*
+ * Multiprocessing Communications Interface (MPCI) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#endif
+#include <rtems/config.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/coresem.h>
+#include <rtems/config.h>
+
+/**
+ * This is the core semaphore which the MPCI Receive Server blocks on.
+ */
+CORE_semaphore_Control _MPCI_Semaphore;
+
+/*PAGE
+ *
+ * _MPCI_Handler_initialization
+ *
+ * This subprogram performs the initialization necessary for this handler.
+ */
+
+void _MPCI_Handler_initialization(
+ uint32_t timeout_status
+)
+{
+ CORE_semaphore_Attributes attributes;
+ MPCI_Control *users_mpci_table;
+
+ users_mpci_table = _Configuration_MP_table->User_mpci_table;
+
+ if ( _System_state_Is_multiprocessing && !users_mpci_table )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_NO_MPCI
+ );
+
+ _MPCI_table = users_mpci_table;
+
+ if ( !_System_state_Is_multiprocessing )
+ return;
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+ _MPCI_Register_packet_processor(
+ MP_PACKET_MPCI_INTERNAL,
+ _MPCI_Internal_packets_Process_packet
+ );
+
+ /*
+ * Create the counting semaphore used by the MPCI Receive Server.
+ */
+
+ attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
+
+ _CORE_semaphore_Initialize(
+ &_MPCI_Semaphore,
+ &attributes, /* the_semaphore_attributes */
+ 0 /* initial_value */
+ );
+
+ _Thread_queue_Initialize(
+ &_MPCI_Remote_blocked_threads,
+ THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_RPC_REPLY,
+ timeout_status
+ );
+}
+
+/*PAGE
+ *
+ * _MPCI_Create_server
+ *
+ * This subprogram creates the MPCI receive server.
+ */
+
+void _MPCI_Create_server( void )
+{
+ Objects_Name name;
+
+
+ if ( !_System_state_Is_multiprocessing )
+ return;
+
+ /*
+ * Initialize the MPCI Receive Server
+ */
+
+ _MPCI_Receive_server_tcb = _Thread_Internal_allocate();
+
+ name.name_u32 = _Objects_Build_name( 'M', 'P', 'C', 'I' );
+ _Thread_Initialize(
+ &_Thread_Internal_information,
+ _MPCI_Receive_server_tcb,
+ NULL, /* allocate the stack */
+ _Stack_Minimum() +
+ CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK +
+ _Configuration_MP_table->extra_mpci_receive_server_stack,
+ CPU_ALL_TASKS_ARE_FP,
+ PRIORITY_MINIMUM,
+ false, /* no preempt */
+ THREAD_CPU_BUDGET_ALGORITHM_NONE,
+ NULL, /* no budget algorithm callout */
+ 0, /* all interrupts enabled */
+ name
+ );
+
+ _Thread_Start(
+ _MPCI_Receive_server_tcb,
+ THREAD_START_NUMERIC,
+ (void *) _MPCI_Receive_server,
+ NULL,
+ 0
+ );
+}
+
+/*PAGE
+ *
+ * _MPCI_Initialization
+ *
+ * This subprogram initializes the MPCI driver by
+ * invoking the user provided MPCI initialization callout.
+ */
+
+void _MPCI_Initialization ( void )
+{
+ (*_MPCI_table->initialization)();
+}
+
+/*PAGE
+ *
+ * _MPCI_Register_packet_processor
+ *
+ * This routine registers the MPCI packet processor for the
+ * designated object class.
+ */
+
+void _MPCI_Register_packet_processor(
+ MP_packet_Classes the_class,
+ MPCI_Packet_processor the_packet_processor
+
+)
+{
+ _MPCI_Packet_processors[ the_class ] = the_packet_processor;
+}
+
+/*PAGE
+ *
+ * _MPCI_Get_packet
+ *
+ * This subprogram obtains a packet by invoking the user provided
+ * MPCI get packet callout.
+ */
+
+MP_packet_Prefix *_MPCI_Get_packet ( void )
+{
+ MP_packet_Prefix *the_packet;
+
+ (*_MPCI_table->get_packet)( &the_packet );
+
+ if ( the_packet == NULL )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_OUT_OF_PACKETS
+ );
+
+ /*
+ * Put in a default timeout that will be used for
+ * all packets that do not otherwise have a timeout.
+ */
+
+ the_packet->timeout = MPCI_DEFAULT_TIMEOUT;
+
+ return the_packet;
+}
+
+/*PAGE
+ *
+ * _MPCI_Return_packet
+ *
+ * This subprogram returns a packet by invoking the user provided
+ * MPCI return packet callout.
+ */
+
+void _MPCI_Return_packet (
+ MP_packet_Prefix *the_packet
+)
+{
+ (*_MPCI_table->return_packet)( the_packet );
+}
+
+/*PAGE
+ *
+ * _MPCI_Send_process_packet
+ *
+ * This subprogram sends a process packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+void _MPCI_Send_process_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet
+)
+{
+ the_packet->source_tid = _Thread_Executing->Object.id;
+ the_packet->to_convert =
+ ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
+
+ (*_MPCI_table->send_packet)( destination, the_packet );
+}
+
+/*PAGE
+ *
+ * _MPCI_Send_request_packet
+ *
+ * This subprogram sends a request packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+uint32_t _MPCI_Send_request_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet,
+ States_Control extra_state
+)
+{
+ the_packet->source_tid = _Thread_Executing->Object.id;
+ the_packet->source_priority = _Thread_Executing->current_priority;
+ the_packet->to_convert =
+ ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) / sizeof(uint32_t);
+
+ _Thread_Executing->Wait.id = the_packet->id;
+
+ _Thread_Executing->Wait.queue = &_MPCI_Remote_blocked_threads;
+
+ _Thread_Disable_dispatch();
+
+ (*_MPCI_table->send_packet)( destination, the_packet );
+
+ _Thread_queue_Enter_critical_section( &_MPCI_Remote_blocked_threads );
+
+ /*
+ * See if we need a default timeout
+ */
+
+ if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
+ the_packet->timeout = _MPCI_table->default_timeout;
+
+ _Thread_queue_Enqueue( &_MPCI_Remote_blocked_threads, the_packet->timeout );
+
+ _Thread_Executing->current_state =
+ _States_Set( extra_state, _Thread_Executing->current_state );
+
+ _Thread_Enable_dispatch();
+
+ return _Thread_Executing->Wait.return_code;
+}
+
+/*PAGE
+ *
+ * _MPCI_Send_response_packet
+ *
+ * This subprogram sends a response packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+void _MPCI_Send_response_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet
+)
+{
+ the_packet->source_tid = _Thread_Executing->Object.id;
+
+ (*_MPCI_table->send_packet)( destination, the_packet );
+}
+
+/*PAGE
+ *
+ * _MPCI_Receive_packet
+ *
+ * This subprogram receives a packet by invoking the user provided
+ * MPCI receive callout.
+ */
+
+MP_packet_Prefix *_MPCI_Receive_packet ( void )
+{
+ MP_packet_Prefix *the_packet;
+
+ (*_MPCI_table->receive_packet)( &the_packet );
+
+ return the_packet;
+}
+
+/*PAGE
+ *
+ * _MPCI_Process_response
+ *
+ * This subprogram obtains a packet by invoking the user provided
+ * MPCI get packet callout.
+ */
+
+Thread_Control *_MPCI_Process_response (
+ MP_packet_Prefix *the_packet
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( the_packet->id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+#if defined(RTEMS_MULTIPROCESSING)
+ case OBJECTS_REMOTE:
+#endif
+ the_thread = NULL; /* IMPOSSIBLE */
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_queue_Extract( &_MPCI_Remote_blocked_threads, the_thread );
+ the_thread->Wait.return_code = the_packet->return_code;
+ _Thread_Unnest_dispatch();
+ break;
+ }
+
+ return the_thread;
+}
+
+/*PAGE
+ *
+ * _MPCI_Receive_server
+ *
+ */
+
+Thread _MPCI_Receive_server(
+ uint32_t ignored
+)
+{
+
+ MP_packet_Prefix *the_packet;
+ MPCI_Packet_processor the_function;
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+
+ for ( ; ; ) {
+
+ executing->receive_packet = NULL;
+
+ _Thread_Disable_dispatch();
+ _CORE_semaphore_Seize( &_MPCI_Semaphore, 0, true, WATCHDOG_NO_TIMEOUT );
+ _Thread_Enable_dispatch();
+
+ for ( ; ; ) {
+ the_packet = _MPCI_Receive_packet();
+
+ if ( !the_packet )
+ break;
+
+ executing->receive_packet = the_packet;
+
+ if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
+ break;
+
+ the_function = _MPCI_Packet_processors[ the_packet->the_class ];
+
+ if ( !the_function )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_BAD_PACKET
+ );
+
+ (*the_function)( the_packet );
+ }
+ }
+
+ return 0; /* unreached - only to remove warnings */
+}
+
+/*PAGE
+ *
+ * _MPCI_Announce
+ *
+ */
+
+void _MPCI_Announce ( void )
+{
+ _Thread_Disable_dispatch();
+ (void) _CORE_semaphore_Surrender( &_MPCI_Semaphore, 0, 0 );
+ _Thread_Enable_dispatch();
+}
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_process_packet
+ *
+ */
+
+void _MPCI_Internal_packets_Send_process_packet (
+ MPCI_Internal_Remote_operations operation
+)
+{
+ MPCI_Internal_packet *the_packet;
+
+ switch ( operation ) {
+
+ case MPCI_PACKETS_SYSTEM_VERIFY:
+
+ the_packet = _MPCI_Internal_packets_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_MPCI_INTERNAL;
+ the_packet->Prefix.length = sizeof ( MPCI_Internal_packet );
+ the_packet->Prefix.to_convert = sizeof ( MPCI_Internal_packet );
+ the_packet->operation = operation;
+
+ the_packet->maximum_nodes = _Objects_Maximum_nodes;
+
+ the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
+
+ _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_request_packet
+ *
+ * This subprogram is not needed since there are no request
+ * packets to be sent by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_response_packet
+ *
+ * This subprogram is not needed since there are no response
+ * packets to be sent by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ *
+ * _MPCI_Internal_packets_Process_packet
+ *
+ */
+
+void _MPCI_Internal_packets_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+)
+{
+ MPCI_Internal_packet *the_packet;
+ uint32_t maximum_nodes;
+ uint32_t maximum_global_objects;
+
+ the_packet = (MPCI_Internal_packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case MPCI_PACKETS_SYSTEM_VERIFY:
+
+ maximum_nodes = the_packet->maximum_nodes;
+ maximum_global_objects = the_packet->maximum_global_objects;
+ if ( maximum_nodes != _Objects_Maximum_nodes ||
+ maximum_global_objects != _Objects_MP_Maximum_global_objects ) {
+
+ _MPCI_Return_packet( the_packet_prefix );
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION
+ );
+ }
+
+ _MPCI_Return_packet( the_packet_prefix );
+
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_object_was_deleted
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_extract_proxy
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Get_packet
+ *
+ */
+
+MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
+{
+ return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
+}
+
+/* end of file */
diff --git a/cpukit/score/src/objectallocate.c b/cpukit/score/src/objectallocate.c
new file mode 100644
index 0000000000..ac98945a74
--- /dev/null
+++ b/cpukit/score/src/objectallocate.c
@@ -0,0 +1,102 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/* #define RTEMS_DEBUG_OBJECT_ALLOCATION */
+
+#if defined(RTEMS_DEBUG_OBJECT_ALLOCATION)
+#include <rtems/bspIo.h>
+#endif
+
+/*PAGE
+ *
+ * _Objects_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a object control block from
+ * the inactive chain of free object control blocks.
+ */
+
+Objects_Control *_Objects_Allocate(
+ Objects_Information *information
+)
+{
+ Objects_Control *the_object;
+
+ /*
+ * If the application is using the optional manager stubs and
+ * still attempts to create the object, the information block
+ * should be all zeroed out because it is in the BSS. So let's
+ * check that code for this manager is even present.
+ */
+ if ( information->size == 0 )
+ return NULL;
+
+ /*
+ * OK. The manager should be initialized and configured to have objects.
+ * With any luck, it is safe to attempt to allocate an object.
+ */
+ the_object = (Objects_Control *) _Chain_Get( &information->Inactive );
+
+ if ( information->auto_extend ) {
+ /*
+ * If the list is empty then we are out of objects and need to
+ * extend information base.
+ */
+
+ if ( !the_object ) {
+ _Objects_Extend_information( information );
+ the_object = (Objects_Control *) _Chain_Get( &information->Inactive );
+ }
+
+ if ( the_object ) {
+ uint32_t block;
+
+ block = (uint32_t) _Objects_Get_index( the_object->id ) -
+ _Objects_Get_index( information->minimum_id );
+ block /= information->allocation_size;
+
+ information->inactive_per_block[ block ]--;
+ information->inactive--;
+ }
+ }
+
+#if defined(RTEMS_DEBUG_OBJECT_ALLOCATION)
+ if ( !the_object ) {
+ printk(
+ "OBJECT ALLOCATION FAILURE! API/Class %d/%d\n",
+ information->the_api,
+ information->the_class
+ );
+ }
+#endif
+
+ return the_object;
+}
diff --git a/cpukit/score/src/objectapimaximumclass.c b/cpukit/score/src/objectapimaximumclass.c
new file mode 100644
index 0000000000..bb61371278
--- /dev/null
+++ b/cpukit/score/src/objectapimaximumclass.c
@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+
+unsigned int _Objects_API_maximum_class(
+ uint32_t api
+)
+{
+ switch (api) {
+ case OBJECTS_INTERNAL_API:
+ return OBJECTS_INTERNAL_CLASSES_LAST;
+ case OBJECTS_CLASSIC_API:
+ return OBJECTS_RTEMS_CLASSES_LAST;
+ case OBJECTS_POSIX_API:
+ return OBJECTS_POSIX_CLASSES_LAST;
+ case OBJECTS_NO_API:
+ default:
+ break;
+ }
+ return 0;
+}
+
diff --git a/cpukit/score/src/objectclose.c b/cpukit/score/src/objectclose.c
new file mode 100644
index 0000000000..1ed76b7fbe
--- /dev/null
+++ b/cpukit/score/src/objectclose.c
@@ -0,0 +1,28 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/wkspace.h>
+
+void _Objects_Close(
+ Objects_Information *information,
+ Objects_Control *the_object
+)
+{
+ _Objects_Invalidate_Id( information, the_object );
+
+ _Objects_Namespace_remove( information, the_object );
+}
diff --git a/cpukit/score/src/objectextendinformation.c b/cpukit/score/src/objectextendinformation.c
new file mode 100644
index 0000000000..0839e0f6be
--- /dev/null
+++ b/cpukit/score/src/objectextendinformation.c
@@ -0,0 +1,266 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+#include <string.h> /* for memcpy() */
+
+/*PAGE
+ *
+ * _Objects_Extend_information
+ *
+ * This routine extends all object information related data structures.
+ *
+ * Input parameters:
+ * information - object information table
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Extend_information(
+ Objects_Information *information
+)
+{
+ Objects_Control *the_object;
+ Chain_Control Inactive;
+ uint32_t block_count;
+ uint32_t block;
+ uint32_t index_base;
+ uint32_t minimum_index;
+ uint32_t index;
+ uint32_t maximum;
+ size_t block_size;
+ void *new_object_block;
+ bool do_extend;
+
+ /*
+ * Search for a free block of indexes. If we do NOT need to allocate or
+ * extend the block table, then we will change do_extend.
+ */
+ do_extend = true;
+ minimum_index = _Objects_Get_index( information->minimum_id );
+ index_base = minimum_index;
+ block = 0;
+
+ /* if ( information->maximum < minimum_index ) */
+ if ( information->object_blocks == NULL )
+ block_count = 0;
+ else {
+ block_count = information->maximum / information->allocation_size;
+
+ for ( ; block < block_count; block++ ) {
+ if ( information->object_blocks[ block ] == NULL ) {
+ do_extend = false;
+ break;
+ } else
+ index_base += information->allocation_size;
+ }
+ }
+
+ maximum = (uint32_t) information->maximum + information->allocation_size;
+
+ /*
+ * We need to limit the number of objects to the maximum number
+ * representable in the index portion of the object Id. In the
+ * case of 16-bit Ids, this is only 256 object instances.
+ */
+ if ( maximum > OBJECTS_ID_FINAL_INDEX ) {
+ return;
+ }
+
+ /*
+ * Allocate the name table, and the objects and if it fails either return or
+ * generate a fatal error depending on auto-extending being active.
+ */
+ block_size = information->allocation_size * information->size;
+ if ( information->auto_extend ) {
+ new_object_block = _Workspace_Allocate( block_size );
+ if ( !new_object_block )
+ return;
+ } else {
+ new_object_block = _Workspace_Allocate_or_fatal_error( block_size );
+ }
+
+ /*
+ * Do we need to grow the tables?
+ */
+ if ( do_extend ) {
+ ISR_Level level;
+ void **object_blocks;
+ uint32_t *inactive_per_block;
+ Objects_Control **local_table;
+ void *old_tables;
+ size_t block_size;
+
+ /*
+ * Growing the tables means allocating a new area, doing a copy and
+ * updating the information table.
+ *
+ * If the maximum is minimum we do not have a table to copy. First
+ * time through.
+ *
+ * The allocation has :
+ *
+ * void *objects[block_count];
+ * uint32_t inactive_count[block_count];
+ * Objects_Control *local_table[maximum];
+ *
+ * This is the order in memory. Watch changing the order. See the memcpy
+ * below.
+ */
+
+ /*
+ * Up the block count and maximum
+ */
+ block_count++;
+
+ /*
+ * Allocate the tables and break it up.
+ */
+ block_size = block_count *
+ (sizeof(void *) + sizeof(uint32_t) + sizeof(Objects_Name *)) +
+ ((maximum + minimum_index) * sizeof(Objects_Control *));
+ object_blocks = (void**) _Workspace_Allocate( block_size );
+
+ if ( !object_blocks ) {
+ _Workspace_Free( new_object_block );
+ return;
+ }
+
+ /*
+ * Break the block into the various sections.
+ */
+ inactive_per_block = (uint32_t *) _Addresses_Add_offset(
+ object_blocks, block_count * sizeof(void*) );
+ local_table = (Objects_Control **) _Addresses_Add_offset(
+ inactive_per_block, block_count * sizeof(uint32_t) );
+
+ /*
+ * Take the block count down. Saves all the (block_count - 1)
+ * in the copies.
+ */
+ block_count--;
+
+ if ( information->maximum > minimum_index ) {
+
+ /*
+ * Copy each section of the table over. This has to be performed as
+ * separate parts as size of each block has changed.
+ */
+
+ memcpy( object_blocks,
+ information->object_blocks,
+ block_count * sizeof(void*) );
+ memcpy( inactive_per_block,
+ information->inactive_per_block,
+ block_count * sizeof(uint32_t) );
+ memcpy( local_table,
+ information->local_table,
+ (information->maximum + minimum_index) * sizeof(Objects_Control *) );
+ } else {
+
+ /*
+ * Deal with the special case of the 0 to minimum_index
+ */
+ for ( index = 0; index < minimum_index; index++ ) {
+ local_table[ index ] = NULL;
+ }
+ }
+
+ /*
+ * Initialise the new entries in the table.
+ */
+ object_blocks[block_count] = NULL;
+ inactive_per_block[block_count] = 0;
+
+ for ( index=index_base ;
+ index < ( information->allocation_size + index_base );
+ index++ ) {
+ local_table[ index ] = NULL;
+ }
+
+ _ISR_Disable( level );
+
+ old_tables = information->object_blocks;
+
+ information->object_blocks = object_blocks;
+ information->inactive_per_block = inactive_per_block;
+ information->local_table = local_table;
+ information->maximum = (Objects_Maximum) maximum;
+ information->maximum_id = _Objects_Build_id(
+ information->the_api,
+ information->the_class,
+ _Objects_Local_node,
+ information->maximum
+ );
+
+ _ISR_Enable( level );
+
+ _Workspace_Free( old_tables );
+
+ block_count++;
+ }
+
+ /*
+ * Assign the new object block to the object block table.
+ */
+ information->object_blocks[ block ] = new_object_block;
+
+ /*
+ * Initialize objects .. add to a local chain first.
+ */
+ _Chain_Initialize(
+ &Inactive,
+ information->object_blocks[ block ],
+ information->allocation_size,
+ information->size
+ );
+
+ /*
+ * Move from the local chain, initialise, then append to the inactive chain
+ */
+ index = index_base;
+
+ while ((the_object = (Objects_Control *) _Chain_Get( &Inactive )) != NULL ) {
+
+ the_object->id = _Objects_Build_id(
+ information->the_api,
+ information->the_class,
+ _Objects_Local_node,
+ index
+ );
+
+ _Chain_Append( &information->Inactive, &the_object->Node );
+
+ index++;
+ }
+
+ information->inactive_per_block[ block ] = information->allocation_size;
+ information->inactive =
+ (Objects_Maximum)(information->inactive + information->allocation_size);
+}
diff --git a/cpukit/score/src/objectfree.c b/cpukit/score/src/objectfree.c
new file mode 100644
index 0000000000..f74394d0fa
--- /dev/null
+++ b/cpukit/score/src/objectfree.c
@@ -0,0 +1,69 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Free
+ *
+ * DESCRIPTION:
+ *
+ * This function frees a object control block to the
+ * inactive chain of free object control blocks.
+ */
+
+void _Objects_Free(
+ Objects_Information *information,
+ Objects_Control *the_object
+)
+{
+ uint32_t allocation_size = information->allocation_size;
+
+ _Chain_Append( &information->Inactive, &the_object->Node );
+
+ if ( information->auto_extend ) {
+ uint32_t block;
+
+ block = (uint32_t) (_Objects_Get_index( the_object->id ) -
+ _Objects_Get_index( information->minimum_id ));
+ block /= information->allocation_size;
+
+ information->inactive_per_block[ block ]++;
+ information->inactive++;
+
+ /*
+ * Check if the threshold level has been met of
+ * 1.5 x allocation_size are free.
+ */
+
+ if ( information->inactive > ( allocation_size + ( allocation_size >> 1 ) ) ) {
+ _Objects_Shrink_information( information );
+ }
+ }
+}
diff --git a/cpukit/score/src/objectget.c b/cpukit/score/src/objectget.c
new file mode 100644
index 0000000000..2abcc389fb
--- /dev/null
+++ b/cpukit/score/src/objectget.c
@@ -0,0 +1,108 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ */
+
+Objects_Control *_Objects_Get(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+
+ /*
+ * Extract the index portion of an Id in a way that produces a valid
+ * index for objects within this class and an invalid value for objects
+ * outside this class.
+ *
+ * If the Id matches the api, class, and node but index portion is 0,
+ * then the subtraction will underflow and the addition of 1 will
+ * result in a 0 index. The zeroth element in the local_table is
+ * always NULL.
+ *
+ * If the Id is valid but the object has not been created yet, then
+ * the local_table entry will be NULL.
+ */
+ index = id - information->minimum_id + 1;
+
+ /*
+ * If the index is less than maximum, then it is OK to use it to
+ * index into the local_table array.
+ */
+ if ( index <= information->maximum ) {
+ _Thread_Disable_dispatch();
+ if ( (the_object = information->local_table[ index ]) != NULL ) {
+ *location = OBJECTS_LOCAL;
+ return the_object;
+ }
+
+ /*
+ * Valid Id for this API, Class and Node but the object has not
+ * been allocated yet.
+ */
+ _Thread_Enable_dispatch();
+ *location = OBJECTS_ERROR;
+ return NULL;
+ }
+
+ /*
+ * Object Id is not within this API and Class on this node. So
+ * it may be global in a multiprocessing system. But it is clearly
+ * invalid on a single processor system.
+ */
+ *location = OBJECTS_ERROR;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Objects_MP_Is_remote( information, id, location, &the_object );
+ return the_object;
+#else
+ return NULL;
+#endif
+}
diff --git a/cpukit/score/src/objectgetinfo.c b/cpukit/score/src/objectgetinfo.c
new file mode 100644
index 0000000000..da3e79713e
--- /dev/null
+++ b/cpukit/score/src/objectgetinfo.c
@@ -0,0 +1,62 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+Objects_Information *_Objects_Get_information(
+ Objects_APIs the_api,
+ uint16_t the_class
+)
+{
+ Objects_Information *info;
+ int the_class_api_maximum;
+
+ if ( !the_class )
+ return NULL;
+
+ /*
+ * This call implicitly validates the_api so we do not call
+ * _Objects_Is_api_valid above here.
+ */
+ the_class_api_maximum = _Objects_API_maximum_class( the_api );
+ if ( the_class_api_maximum == 0 )
+ return NULL;
+
+ if ( the_class > (uint32_t) the_class_api_maximum )
+ return NULL;
+
+ if ( !_Objects_Information_table[ the_api ] )
+ return NULL;
+
+ info = _Objects_Information_table[ the_api ][ the_class ];
+ if ( !info )
+ return NULL;
+
+ /*
+ * In a multprocessing configuration, we may access remote objects.
+ * Thus we may have 0 local instances and still have a valid object
+ * pointer.
+ */
+ #if !defined(RTEMS_MULTIPROCESSING)
+ if ( info->maximum == 0 )
+ return NULL;
+ #endif
+
+ return info;
+}
+
diff --git a/cpukit/score/src/objectgetinfoid.c b/cpukit/score/src/objectgetinfoid.c
new file mode 100644
index 0000000000..729135a9dc
--- /dev/null
+++ b/cpukit/score/src/objectgetinfoid.c
@@ -0,0 +1,28 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+
+Objects_Information *_Objects_Get_information_id(
+ Objects_Id id
+)
+{
+ return _Objects_Get_information(
+ _Objects_Get_API( id ),
+ _Objects_Get_class( id )
+ );
+}
diff --git a/cpukit/score/src/objectgetisr.c b/cpukit/score/src/objectgetisr.c
new file mode 100644
index 0000000000..aca5f0d059
--- /dev/null
+++ b/cpukit/score/src/objectgetisr.c
@@ -0,0 +1,86 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_isr_disable
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ * level - pointer to previous interrupt level
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ * *level - previous interrupt level
+ */
+
+Objects_Control *_Objects_Get_isr_disable(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location,
+ ISR_Level *level_p
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+ ISR_Level level;
+
+ index = id - information->minimum_id + 1;
+
+ _ISR_Disable( level );
+ if ( information->maximum >= index ) {
+ if ( (the_object = information->local_table[ index ]) != NULL ) {
+ *location = OBJECTS_LOCAL;
+ *level_p = level;
+ return the_object;
+ }
+ _ISR_Enable( level );
+ *location = OBJECTS_ERROR;
+ return NULL;
+ }
+ _ISR_Enable( level );
+ *location = OBJECTS_ERROR;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Objects_MP_Is_remote( information, id, location, &the_object );
+ return the_object;
+#else
+ return NULL;
+#endif
+}
diff --git a/cpukit/score/src/objectgetnameasstring.c b/cpukit/score/src/objectgetnameasstring.c
new file mode 100644
index 0000000000..4c15cd9811
--- /dev/null
+++ b/cpukit/score/src/objectgetnameasstring.c
@@ -0,0 +1,96 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+/*
+ * This method objects the name of an object and returns its name
+ * in the form of a C string. It attempts to be careful about
+ * overflowing the user's string and about returning unprintable characters.
+ */
+
+char *_Objects_Get_name_as_string(
+ Objects_Id id,
+ size_t length,
+ char *name
+)
+{
+ Objects_Information *information;
+ const char *s;
+ char *d;
+ uint32_t i;
+ char lname[5];
+ Objects_Control *the_object;
+ Objects_Locations location;
+ Objects_Id tmpId;
+
+ if ( length == 0 )
+ return NULL;
+
+ if ( name == NULL )
+ return NULL;
+
+ tmpId = (id == OBJECTS_ID_OF_SELF) ? _Thread_Executing->Object.id : id;
+
+ information = _Objects_Get_information_id( tmpId );
+ if ( !information )
+ return NULL;
+
+ the_object = _Objects_Get( information, tmpId, &location );
+ switch ( location ) {
+
+#if defined(RTEMS_MULTIPROCESSING)
+ case OBJECTS_REMOTE:
+ /* not supported */
+#endif
+ case OBJECTS_ERROR:
+ return NULL;
+
+ case OBJECTS_LOCAL:
+
+ #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+ if ( information->is_string ) {
+ s = the_object->name.name_p;
+ } else
+ #endif
+ {
+ uint32_t u32_name = (uint32_t) the_object->name.name_u32;
+
+ lname[ 0 ] = (u32_name >> 24) & 0xff;
+ lname[ 1 ] = (u32_name >> 16) & 0xff;
+ lname[ 2 ] = (u32_name >> 8) & 0xff;
+ lname[ 3 ] = (u32_name >> 0) & 0xff;
+ lname[ 4 ] = '\0';
+ s = lname;
+ }
+
+ d = name;
+ if ( s ) {
+ for ( i=0 ; i<(length-1) && *s ; i++, s++, d++ ) {
+ *d = (isprint((unsigned char)*s)) ? *s : '*';
+ }
+ }
+ *d = '\0';
+
+ _Thread_Enable_dispatch();
+ return name;
+ }
+ return NULL; /* unreachable path */
+}
diff --git a/cpukit/score/src/objectgetnext.c b/cpukit/score/src/objectgetnext.c
new file mode 100644
index 0000000000..206dbf3134
--- /dev/null
+++ b/cpukit/score/src/objectgetnext.c
@@ -0,0 +1,103 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_next
+ *
+ * Like _Objects_Get, but considers the 'id' as a "hint" and
+ * finds next valid one after that point.
+ * Mostly used for monitor and debug traversal of an object.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ * next_id - address to store next id to try
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ * next_id - will contain a reasonable "next" id to continue traversal
+ *
+ * NOTE:
+ * assumes can add '1' to an id to get to next index.
+ */
+
+Objects_Control *
+_Objects_Get_next(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location_p,
+ Objects_Id *next_id_p
+)
+{
+ Objects_Control *object;
+ Objects_Id next_id;
+
+ if ( !information )
+ return NULL;
+
+ if ( !location_p )
+ return NULL;
+
+ if ( !next_id_p )
+ return NULL;
+
+ if (_Objects_Get_index(id) == OBJECTS_ID_INITIAL_INDEX)
+ next_id = information->minimum_id;
+ else
+ next_id = id;
+
+ do {
+ /* walked off end of list? */
+ if (_Objects_Get_index(next_id) > information->maximum)
+ {
+ *location_p = OBJECTS_ERROR;
+ goto final;
+ }
+
+ /* try to grab one */
+ object = _Objects_Get(information, next_id, location_p);
+
+ next_id++;
+
+ } while (*location_p != OBJECTS_LOCAL);
+
+ *next_id_p = next_id;
+ return object;
+
+final:
+ *next_id_p = OBJECTS_ID_FINAL;
+ return 0;
+}
diff --git a/cpukit/score/src/objectgetnoprotection.c b/cpukit/score/src/objectgetnoprotection.c
new file mode 100644
index 0000000000..d969477747
--- /dev/null
+++ b/cpukit/score/src/objectgetnoprotection.c
@@ -0,0 +1,79 @@
+/*
+ * Object Handler -- Object Get
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_no_protection
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ */
+
+Objects_Control *_Objects_Get_no_protection(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+
+ /*
+ * You can't just extract the index portion or you can get tricked
+ * by a value between 1 and maximum.
+ */
+ index = id - information->minimum_id + 1;
+
+ if ( information->maximum >= index ) {
+ if ( (the_object = information->local_table[ index ]) != NULL ) {
+ *location = OBJECTS_LOCAL;
+ return the_object;
+ }
+ }
+
+ /*
+ * This isn't supported or required yet for Global objects so
+ * if it isn't local, we don't find it.
+ */
+ *location = OBJECTS_ERROR;
+ return NULL;
+}
diff --git a/cpukit/score/src/objectidtoname.c b/cpukit/score/src/objectidtoname.c
new file mode 100644
index 0000000000..870d424986
--- /dev/null
+++ b/cpukit/score/src/objectidtoname.c
@@ -0,0 +1,79 @@
+/*
+ * Obtain Object Name Given ID
+ *
+ *
+ * COPYRIGHT (c) 1989-2003.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+
+/*
+ * _Objects_Id_to_name
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the name associated with the given ID.
+ *
+ * INPUT:
+ *
+ * id - id of object to lookup name
+ * name - pointer to location in which to store name
+ *
+ */
+Objects_Name_or_id_lookup_errors _Objects_Id_to_name (
+ Objects_Id id,
+ Objects_Name *name
+)
+{
+ uint32_t the_api;
+ uint32_t the_class;
+ Objects_Id tmpId;
+ Objects_Information *information;
+ Objects_Control *the_object = (Objects_Control *) 0;
+ Objects_Locations ignored_location;
+
+ /*
+ * Caller is trusted for name != NULL.
+ */
+
+ tmpId = (id == OBJECTS_ID_OF_SELF) ? _Thread_Executing->Object.id : id;
+
+ the_api = _Objects_Get_API( tmpId );
+ if ( !_Objects_Is_api_valid( the_api ) )
+ return OBJECTS_INVALID_ID;
+
+ if ( !_Objects_Information_table[ the_api ] )
+ return OBJECTS_INVALID_ID;
+
+ the_class = _Objects_Get_class( tmpId );
+
+ information = _Objects_Information_table[ the_api ][ the_class ];
+ if ( !information )
+ return OBJECTS_INVALID_ID;
+
+ #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+ if ( information->is_string )
+ return OBJECTS_INVALID_ID;
+ #endif
+
+ the_object = _Objects_Get( information, tmpId, &ignored_location );
+ if ( !the_object )
+ return OBJECTS_INVALID_ID;
+
+ *name = the_object->name;
+ _Thread_Enable_dispatch();
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/objectinitializeinformation.c b/cpukit/score/src/objectinitializeinformation.c
new file mode 100644
index 0000000000..b59b64ae97
--- /dev/null
+++ b/cpukit/score/src/objectinitializeinformation.c
@@ -0,0 +1,178 @@
+/*
+ * Object Handler Initialization per Object Class
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Initialize_information
+ *
+ * This routine initializes all object information related data structures.
+ *
+ * Input parameters:
+ * information - object information table
+ * maximum - maximum objects of this class
+ * size - size of this object's control block
+ * is_string - true if names for this object are strings
+ * maximum_name_length - maximum length of each object's name
+ * When multiprocessing is configured,
+ * supports_global - true if this is a global object class
+ * extract_callout - pointer to threadq extract callout
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Initialize_information(
+ Objects_Information *information,
+ Objects_APIs the_api,
+ uint16_t the_class,
+ uint32_t maximum,
+ uint16_t size,
+ bool is_string,
+ uint32_t maximum_name_length
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ bool supports_global,
+ Objects_Thread_queue_Extract_callout extract
+#endif
+)
+{
+ static Objects_Control *null_local_table = NULL;
+ uint32_t minimum_index;
+ uint32_t name_length;
+ uint32_t maximum_per_allocation;
+ #if defined(RTEMS_MULTIPROCESSING)
+ uint32_t index;
+ #endif
+
+ information->the_api = the_api;
+ information->the_class = the_class;
+ information->size = size;
+ information->local_table = 0;
+ information->inactive_per_block = 0;
+ information->object_blocks = 0;
+ information->inactive = 0;
+ #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+ information->is_string = is_string;
+ #endif
+
+ /*
+ * Set the maximum value to 0. It will be updated when objects are
+ * added to the inactive set from _Objects_Extend_information()
+ */
+ information->maximum = 0;
+
+ /*
+ * Register this Object Class in the Object Information Table.
+ */
+ _Objects_Information_table[ the_api ][ the_class ] = information;
+
+ /*
+ * Are we operating in limited or unlimited (e.g. auto-extend) mode.
+ */
+ information->auto_extend =
+ (maximum & OBJECTS_UNLIMITED_OBJECTS) ? true : false;
+ maximum_per_allocation = maximum & ~OBJECTS_UNLIMITED_OBJECTS;
+
+ /*
+ * Unlimited and maximum of zero is illogical.
+ */
+ if ( information->auto_extend && maximum_per_allocation == 0) {
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0
+ );
+ }
+
+ /*
+ * The allocation unit is the maximum value
+ */
+ information->allocation_size = maximum_per_allocation;
+
+ /*
+ * Provide a null local table entry for the case of any empty table.
+ */
+ information->local_table = &null_local_table;
+
+ /*
+ * Calculate minimum and maximum Id's
+ */
+ minimum_index = (maximum_per_allocation == 0) ? 0 : 1;
+ information->minimum_id =
+ _Objects_Build_id( the_api, the_class, _Objects_Local_node, minimum_index );
+
+ /*
+ * Calculate the maximum name length
+ *
+ * NOTE: Always 4 bytes long in Class so aligned. It is POSIX name
+ * lengths that may be an odd number of bytes.
+ */
+ name_length = maximum_name_length;
+
+ #if defined(RTEMS_POSIX_API)
+ if ( name_length & (OBJECTS_NAME_ALIGNMENT-1) )
+ name_length = (name_length + OBJECTS_NAME_ALIGNMENT) &
+ ~(OBJECTS_NAME_ALIGNMENT-1);
+ #endif
+
+ information->name_length = name_length;
+
+ _Chain_Initialize_empty( &information->Inactive );
+
+ /*
+ * Initialize objects .. if there are any
+ */
+ if ( maximum_per_allocation ) {
+ /*
+ * Always have the maximum size available so the current performance
+ * figures are create are met. If the user moves past the maximum
+ * number then a performance hit is taken.
+ */
+ _Objects_Extend_information( information );
+ }
+
+ /*
+ * Take care of multiprocessing
+ */
+ #if defined(RTEMS_MULTIPROCESSING)
+ information->extract = extract;
+
+ if ( (supports_global == true) && _System_state_Is_multiprocessing ) {
+
+ information->global_table =
+ (Chain_Control *) _Workspace_Allocate_or_fatal_error(
+ (_Objects_Maximum_nodes + 1) * sizeof(Chain_Control)
+ );
+
+ for ( index=1; index <= _Objects_Maximum_nodes ; index++ )
+ _Chain_Initialize_empty( &information->global_table[ index ] );
+ }
+ else
+ information->global_table = NULL;
+ #endif
+}
diff --git a/cpukit/score/src/objectmp.c b/cpukit/score/src/objectmp.c
new file mode 100644
index 0000000000..5564b52f1f
--- /dev/null
+++ b/cpukit/score/src/objectmp.c
@@ -0,0 +1,307 @@
+/*
+ * Multiprocessing Support for the Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * _Objects_MP_Handler_early_initialization
+ *
+ */
+void _Objects_MP_Handler_early_initialization(void)
+{
+ uint32_t node;
+ uint32_t maximum_nodes;
+
+ node = _Configuration_MP_table->node;
+ maximum_nodes = _Configuration_MP_table->maximum_nodes;
+
+ if ( node < 1 || node > maximum_nodes )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_INVALID_NODE
+ );
+
+ _Objects_Local_node = node;
+ _Objects_Maximum_nodes = maximum_nodes;
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Handler_initialization
+ *
+ */
+
+void _Objects_MP_Handler_initialization(void)
+{
+
+ uint32_t maximum_global_objects;
+
+ maximum_global_objects = _Configuration_MP_table->maximum_global_objects;
+
+ _Objects_MP_Maximum_global_objects = maximum_global_objects;
+
+ if ( maximum_global_objects == 0 ) {
+ _Chain_Initialize_empty( &_Objects_MP_Inactive_global_objects );
+ return;
+ }
+
+ _Chain_Initialize(
+ &_Objects_MP_Inactive_global_objects,
+ _Workspace_Allocate_or_fatal_error(
+ maximum_global_objects * sizeof( Objects_MP_Control )
+ ),
+ maximum_global_objects,
+ sizeof( Objects_MP_Control )
+ );
+
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Open
+ *
+ */
+
+void _Objects_MP_Open (
+ Objects_Information *information,
+ Objects_MP_Control *the_global_object,
+ uint32_t the_name, /* XXX -- wrong for variable */
+ Objects_Id the_id
+)
+{
+ the_global_object->Object.id = the_id;
+ the_global_object->name = the_name;
+
+ _Chain_Prepend(
+ &information->global_table[ _Objects_Get_node( the_id ) ],
+ &the_global_object->Object.Node
+ );
+
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Allocate_and_open
+ *
+ */
+
+bool _Objects_MP_Allocate_and_open (
+ Objects_Information *information,
+ uint32_t the_name, /* XXX -- wrong for variable */
+ Objects_Id the_id,
+ bool is_fatal_error
+)
+{
+ Objects_MP_Control *the_global_object;
+
+ the_global_object = _Objects_MP_Allocate_global_object();
+ if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
+
+ if ( is_fatal_error == false )
+ return false;
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS
+ );
+
+ }
+
+ _Objects_MP_Open( information, the_global_object, the_name, the_id );
+
+ return true;
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Close
+ *
+ */
+
+void _Objects_MP_Close (
+ Objects_Information *information,
+ Objects_Id the_id
+)
+{
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ Objects_MP_Control *the_object;
+
+ the_chain = &information->global_table[ _Objects_Get_node( the_id ) ];
+
+ for ( the_node = _Chain_First( the_chain ) ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = _Chain_Next( the_node ) ) {
+
+ the_object = (Objects_MP_Control *) the_node;
+
+ if ( _Objects_Are_ids_equal( the_object->Object.id, the_id ) ) {
+
+ _Chain_Extract( the_node );
+ _Objects_MP_Free_global_object( the_object );
+ return;
+ }
+
+ }
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_INVALID_GLOBAL_ID
+ );
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Global_name_search
+ *
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_MP_Global_name_search (
+ Objects_Information *information,
+ Objects_Name the_name,
+ uint32_t nodes_to_search,
+ Objects_Id *the_id
+)
+{
+ uint32_t low_node;
+ uint32_t high_node;
+ uint32_t node_index;
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ Objects_MP_Control *the_object;
+ uint32_t name_to_use;
+
+ name_to_use = the_name.name_u32; /* XXX only fixed length names */
+
+ if ( nodes_to_search > _Objects_Maximum_nodes )
+ return OBJECTS_INVALID_NODE;
+
+ if ( information->global_table == NULL )
+ return OBJECTS_INVALID_NAME;
+
+ if ( nodes_to_search == OBJECTS_SEARCH_ALL_NODES ||
+ nodes_to_search == OBJECTS_SEARCH_OTHER_NODES ) {
+ low_node = 1;
+ high_node = _Objects_Maximum_nodes;
+ } else {
+ low_node =
+ high_node = nodes_to_search;
+ }
+
+ _Thread_Disable_dispatch();
+
+ for ( node_index = low_node ; node_index <= high_node ; node_index++ ) {
+
+ /*
+ * NOTE: The local node was search (if necessary) by
+ * _Objects_Name_to_id_XXX before this was invoked.
+ */
+
+ if ( !_Objects_Is_local_node( node_index ) ) {
+ the_chain = &information->global_table[ node_index ];
+
+ for ( the_node = _Chain_First( the_chain ) ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = _Chain_Next( the_node ) ) {
+
+ the_object = (Objects_MP_Control *) the_node;
+
+ if ( the_object->name == name_to_use ) {
+ *the_id = the_object->Object.id;
+ _Thread_Enable_dispatch();
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+ }
+ }
+ }
+ }
+
+ _Thread_Enable_dispatch();
+ return OBJECTS_INVALID_NAME;
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Is_remote
+ *
+ */
+
+void _Objects_MP_Is_remote (
+ Objects_Information *information,
+ Objects_Id the_id,
+ Objects_Locations *location,
+ Objects_Control **the_object
+)
+{
+ uint32_t node;
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ Objects_MP_Control *the_global_object;
+
+ node = _Objects_Get_node( the_id );
+
+ /*
+ * NOTE: The local node was search (if necessary) by
+ * _Objects_Name_to_id_XXX before this was invoked.
+ *
+ * The NODE field of an object id cannot be 0
+ * because 0 is an invalid node number.
+ */
+
+ if ( node == 0 ||
+ _Objects_Is_local_node( node ) ||
+ node > _Objects_Maximum_nodes ||
+ information->global_table == NULL ) {
+
+ *location = OBJECTS_ERROR;
+ *the_object = NULL;
+ return;
+ }
+
+ _Thread_Disable_dispatch();
+
+ the_chain = &information->global_table[ node ];
+
+ for ( the_node = _Chain_First( the_chain ) ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = _Chain_Next( the_node ) ) {
+
+ the_global_object = (Objects_MP_Control *) the_node;
+
+ if ( _Objects_Are_ids_equal( the_global_object->Object.id, the_id ) ) {
+ _Thread_Unnest_dispatch();
+ *location = OBJECTS_REMOTE;
+ *the_object = (Objects_Control *) the_global_object;
+ return;
+ }
+ }
+
+ _Thread_Enable_dispatch();
+ *location = OBJECTS_ERROR;
+ *the_object = NULL;
+
+}
+
diff --git a/cpukit/score/src/objectnamespaceremove.c b/cpukit/score/src/objectnamespaceremove.c
new file mode 100644
index 0000000000..d6c0968f90
--- /dev/null
+++ b/cpukit/score/src/objectnamespaceremove.c
@@ -0,0 +1,40 @@
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/wkspace.h>
+
+void _Objects_Namespace_remove(
+ Objects_Information *information,
+ Objects_Control *the_object
+)
+{
+ #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+ /*
+ * If this is a string format name, then free the memory.
+ */
+ if ( information->is_string )
+ _Workspace_Free( (void *)the_object->name.name_p );
+ #endif
+
+ /*
+ * Clear out either format.
+ */
+ #if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+ the_object->name.name_p = NULL;
+ #endif
+ the_object->name.name_u32 = 0;
+}
diff --git a/cpukit/score/src/objectnametoid.c b/cpukit/score/src/objectnametoid.c
new file mode 100644
index 0000000000..9cd75a274c
--- /dev/null
+++ b/cpukit/score/src/objectnametoid.c
@@ -0,0 +1,102 @@
+/*
+ * Object Handler
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Name_to_id_u32
+ *
+ * These kernel routines search the object table(s) for the given
+ * object name and returns the associated object id.
+ *
+ * Input parameters:
+ * information - object information
+ * name - user defined object name
+ * node - node indentifier (0 indicates any node)
+ * id - address of return ID
+ *
+ * Output parameters:
+ * id - object id
+ * OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_Name_to_id_u32(
+ Objects_Information *information,
+ uint32_t name,
+ uint32_t node,
+ Objects_Id *id
+)
+{
+ bool search_local_node;
+ Objects_Control *the_object;
+ uint32_t index;
+#if defined(RTEMS_MULTIPROCESSING)
+ Objects_Name name_for_mp;
+#endif
+
+ /* ASSERT: information->is_string == false */
+
+ if ( !id )
+ return OBJECTS_INVALID_ADDRESS;
+
+ if ( name == 0 )
+ return OBJECTS_INVALID_NAME;
+
+ search_local_node = false;
+
+ if ( information->maximum != 0 &&
+ (node == OBJECTS_SEARCH_ALL_NODES ||
+ node == OBJECTS_SEARCH_LOCAL_NODE ||
+ _Objects_Is_local_node( node )
+ ))
+ search_local_node = true;
+
+ if ( search_local_node ) {
+ for ( index = 1; index <= information->maximum; index++ ) {
+ the_object = information->local_table[ index ];
+ if ( !the_object )
+ continue;
+
+ if ( name == the_object->name.name_u32 ) {
+ *id = the_object->id;
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+ }
+ }
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Objects_Is_local_node( node ) || node == OBJECTS_SEARCH_LOCAL_NODE )
+ return OBJECTS_INVALID_NAME;
+
+ name_for_mp.name_u32 = name;
+ return _Objects_MP_Global_name_search( information, name_for_mp, node, id );
+#else
+ return OBJECTS_INVALID_NAME;
+#endif
+}
diff --git a/cpukit/score/src/objectnametoidstring.c b/cpukit/score/src/objectnametoidstring.c
new file mode 100644
index 0000000000..17b43d725d
--- /dev/null
+++ b/cpukit/score/src/objectnametoidstring.c
@@ -0,0 +1,87 @@
+/*
+ * Object Handler - Object ID to Name (String)
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+#if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+/*PAGE
+ *
+ * _Objects_Name_to_id_string
+ *
+ * These kernel routines search the object table(s) for the given
+ * object name and returns the associated object id.
+ *
+ * Input parameters:
+ * information - object information
+ * name - user defined object name
+ * id - address of return ID
+ *
+ * Output parameters:
+ * id - object id
+ * OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_Name_to_id_string(
+ Objects_Information *information,
+ const char *name,
+ Objects_Id *id
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+
+ /* ASSERT: information->is_string == true */
+
+ if ( !id )
+ return OBJECTS_INVALID_ADDRESS;
+
+ if ( !name )
+ return OBJECTS_INVALID_NAME;
+
+ if ( information->maximum != 0 ) {
+
+ for ( index = 1; index <= information->maximum; index++ ) {
+ the_object = information->local_table[ index ];
+ if ( !the_object )
+ continue;
+
+ if ( !the_object->name.name_p )
+ continue;
+
+ if (!strncmp( name, the_object->name.name_p, information->name_length)) {
+ *id = the_object->id;
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+ }
+ }
+ }
+
+ return OBJECTS_INVALID_NAME;
+}
+#endif
diff --git a/cpukit/score/src/objectsetname.c b/cpukit/score/src/objectsetname.c
new file mode 100644
index 0000000000..793e0914dd
--- /dev/null
+++ b/cpukit/score/src/objectsetname.c
@@ -0,0 +1,69 @@
+/*
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <string.h>
+
+
+/*
+ * This method sets the name of an object based upon a C string.
+ */
+
+bool _Objects_Set_name(
+ Objects_Information *information,
+ Objects_Control *the_object,
+ const char *name
+)
+{
+ size_t length;
+ const char *s;
+
+ s = name;
+ length = strnlen( name, information->name_length );
+
+#if defined(RTEMS_SCORE_OBJECT_ENABLE_STRING_NAMES)
+ if ( information->is_string ) {
+ char *d;
+
+ d = _Workspace_Allocate( length + 1 );
+ if ( !d )
+ return false;
+
+ _Workspace_Free( (void *)the_object->name.name_p );
+ the_object->name.name_p = NULL;
+
+ strncpy( d, name, length );
+ d[length] = '\0';
+ the_object->name.name_p = d;
+ } else
+#endif
+ {
+ the_object->name.name_u32 = _Objects_Build_name(
+ ((0 <= length) ? s[ 0 ] : ' '),
+ ((1 < length) ? s[ 1 ] : ' '),
+ ((2 < length) ? s[ 2 ] : ' '),
+ ((3 < length) ? s[ 3 ] : ' ')
+ );
+
+ }
+
+ return true;
+}
diff --git a/cpukit/score/src/objectshrinkinformation.c b/cpukit/score/src/objectshrinkinformation.c
new file mode 100644
index 0000000000..18123fab68
--- /dev/null
+++ b/cpukit/score/src/objectshrinkinformation.c
@@ -0,0 +1,102 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Shrink_information
+ *
+ * This routine shrinks object information related data structures.
+ * The object's name and object space are released. The local_table
+ * etc block does not shrink. The InActive list needs to be scanned
+ * to find the objects are remove them.
+ * Input parameters:
+ * information - object information table
+ * the_block - the block to remove
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Shrink_information(
+ Objects_Information *information
+)
+{
+ Objects_Control *the_object;
+ Objects_Control *extract_me;
+ uint32_t block_count;
+ uint32_t block;
+ uint32_t index_base;
+ uint32_t index;
+
+ /*
+ * Search the list to find block or chunk with all objects inactive.
+ */
+
+ index_base = _Objects_Get_index( information->minimum_id );
+ block_count = (information->maximum - index_base) /
+ information->allocation_size;
+
+ for ( block = 0; block < block_count; block++ ) {
+ if ( information->inactive_per_block[ block ] ==
+ information->allocation_size ) {
+
+ /*
+ * Assume the Inactive chain is never empty at this point
+ */
+ the_object = (Objects_Control *) _Chain_First( &information->Inactive );
+
+ do {
+ index = _Objects_Get_index( the_object->id );
+ /*
+ * Get the next node before the node is extracted
+ */
+ extract_me = the_object;
+ the_object = (Objects_Control *) the_object->Node.next;
+ if ((index >= index_base) &&
+ (index < (index_base + information->allocation_size))) {
+ _Chain_Extract( &extract_me->Node );
+ }
+ }
+ while ( the_object );
+ /*
+ * Free the memory and reset the structures in the object' information
+ */
+
+ _Workspace_Free( information->object_blocks[ block ] );
+ information->object_blocks[ block ] = NULL;
+ information->inactive_per_block[ block ] = 0;
+
+ information->inactive -= information->allocation_size;
+
+ return;
+ }
+
+ index_base += information->allocation_size;
+ }
+}
diff --git a/cpukit/score/src/percpu.c b/cpukit/score/src/percpu.c
new file mode 100644
index 0000000000..2d429b4db9
--- /dev/null
+++ b/cpukit/score/src/percpu.c
@@ -0,0 +1,64 @@
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/config.h>
+#include <rtems/bspsmp.h>
+#include <string.h>
+
+#if defined(RTEMS_SMP)
+ void _SMP_Handler_initialize(void)
+ {
+ int cpu;
+ size_t size;
+ uintptr_t ptr;
+
+ /*
+ * Initialize per CPU structures.
+ */
+ size = (_SMP_Processor_count) * sizeof(Per_CPU_Control);
+ memset( _Per_CPU_Information, '\0', size );
+
+ /*
+ * Initialize per cpu pointer table
+ */
+ size = Configuration.interrupt_stack_size;
+ _Per_CPU_Information_p[0] = &_Per_CPU_Information[0];
+ for (cpu=1 ; cpu < _SMP_Processor_count ; cpu++ ) {
+ Per_CPU_Control *p = &_Per_CPU_Information[cpu];
+
+ _Per_CPU_Information_p[cpu] = p;
+
+ p->interrupt_stack_low = _Workspace_Allocate_or_fatal_error( size );
+
+ ptr = (uintptr_t) _Addresses_Add_offset( p->interrupt_stack_low, size );
+ ptr &= ~CPU_STACK_ALIGNMENT;
+ p->interrupt_stack_high = (void *)ptr;
+ p->state = RTEMS_BSP_SMP_CPU_INITIAL_STATE;
+ RTEMS_COMPILER_MEMORY_BARRIER();
+ }
+ }
+#else
+ /*
+ * On single core systems, we can efficiently directly access a single
+ * statically allocated per cpu structure. And the fields are initialized
+ * as individual elements just like it has always been done.
+ */
+ Per_CPU_Control _Per_CPU_Information[1];
+#endif
diff --git a/cpukit/score/src/pheapallocate.c b/cpukit/score/src/pheapallocate.c
new file mode 100644
index 0000000000..b4888dc8ea
--- /dev/null
+++ b/cpukit/score/src/pheapallocate.c
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+void *_Protected_heap_Allocate_aligned_with_boundary(
+ Heap_Control *heap,
+ uintptr_t size,
+ uintptr_t alignment,
+ uintptr_t boundary
+)
+{
+ void *p;
+
+ _RTEMS_Lock_allocator();
+ p = _Heap_Allocate_aligned_with_boundary(
+ heap,
+ size,
+ alignment,
+ boundary
+ );
+ _RTEMS_Unlock_allocator();
+
+ return p;
+}
diff --git a/cpukit/score/src/pheapextend.c b/cpukit/score/src/pheapextend.c
new file mode 100644
index 0000000000..e71fb1bd8c
--- /dev/null
+++ b/cpukit/score/src/pheapextend.c
@@ -0,0 +1,41 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Extend(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uintptr_t size
+)
+{
+ bool extend_ok;
+ uintptr_t amount_extended;
+
+ _RTEMS_Lock_allocator();
+ extend_ok = _Heap_Extend(the_heap, starting_address, size, &amount_extended);
+ _RTEMS_Unlock_allocator();
+ return extend_ok;
+}
+
diff --git a/cpukit/score/src/pheapfree.c b/cpukit/score/src/pheapfree.c
new file mode 100644
index 0000000000..eb57ded669
--- /dev/null
+++ b/cpukit/score/src/pheapfree.c
@@ -0,0 +1,38 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Free(
+ Heap_Control *the_heap,
+ void *start_address
+)
+{
+ bool status;
+
+ _RTEMS_Lock_allocator();
+ status = _Heap_Free( the_heap, start_address );
+ _RTEMS_Unlock_allocator();
+ return status;
+}
diff --git a/cpukit/score/src/pheapgetblocksize.c b/cpukit/score/src/pheapgetblocksize.c
new file mode 100644
index 0000000000..0591abdd6e
--- /dev/null
+++ b/cpukit/score/src/pheapgetblocksize.c
@@ -0,0 +1,39 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Get_block_size(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uintptr_t *size
+)
+{
+ bool status;
+
+ _RTEMS_Lock_allocator();
+ status = _Heap_Size_of_alloc_area( the_heap, starting_address, size );
+ _RTEMS_Unlock_allocator();
+ return status;
+}
diff --git a/cpukit/score/src/pheapgetfreeinfo.c b/cpukit/score/src/pheapgetfreeinfo.c
new file mode 100644
index 0000000000..e95bffe0ba
--- /dev/null
+++ b/cpukit/score/src/pheapgetfreeinfo.c
@@ -0,0 +1,42 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Get_free_information(
+ Heap_Control *the_heap,
+ Heap_Information *info
+)
+{
+ /*
+ * TBD: _Heap_Get_free_information does not error check or return status.
+ */
+
+ _RTEMS_Lock_allocator();
+ _Heap_Get_free_information( the_heap, info );
+ _RTEMS_Unlock_allocator();
+
+ return true;
+}
+
diff --git a/cpukit/score/src/pheapgetinfo.c b/cpukit/score/src/pheapgetinfo.c
new file mode 100644
index 0000000000..2c4a287edd
--- /dev/null
+++ b/cpukit/score/src/pheapgetinfo.c
@@ -0,0 +1,43 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Get_information(
+ Heap_Control *the_heap,
+ Heap_Information_block *the_info
+)
+{
+ if ( !the_heap )
+ return false;
+
+ if ( !the_info )
+ return false;
+
+ _RTEMS_Lock_allocator();
+ _Heap_Get_information( the_heap, the_info );
+ _RTEMS_Unlock_allocator();
+
+ return true;
+}
diff --git a/cpukit/score/src/pheapgetsize.c b/cpukit/score/src/pheapgetsize.c
new file mode 100644
index 0000000000..fbf90ea3a4
--- /dev/null
+++ b/cpukit/score/src/pheapgetsize.c
@@ -0,0 +1,32 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+uintptr_t _Protected_heap_Get_size(
+ Heap_Control *the_heap
+)
+{
+ return _Heap_Get_size( the_heap );
+}
diff --git a/cpukit/score/src/pheapinit.c b/cpukit/score/src/pheapinit.c
new file mode 100644
index 0000000000..f2a11a7be9
--- /dev/null
+++ b/cpukit/score/src/pheapinit.c
@@ -0,0 +1,27 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+
diff --git a/cpukit/score/src/pheapresizeblock.c b/cpukit/score/src/pheapresizeblock.c
new file mode 100644
index 0000000000..14dc522cff
--- /dev/null
+++ b/cpukit/score/src/pheapresizeblock.c
@@ -0,0 +1,43 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Resize_block(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uintptr_t size
+)
+{
+ Heap_Resize_status status;
+ uintptr_t old_mem_size;
+ uintptr_t avail_mem_size;
+
+ _RTEMS_Lock_allocator();
+ status = _Heap_Resize_block(
+ the_heap, starting_address, size, &old_mem_size, &avail_mem_size );
+ _RTEMS_Unlock_allocator();
+ return (status == HEAP_RESIZE_SUCCESSFUL);
+}
+
diff --git a/cpukit/score/src/pheapwalk.c b/cpukit/score/src/pheapwalk.c
new file mode 100644
index 0000000000..4aa2279902
--- /dev/null
+++ b/cpukit/score/src/pheapwalk.c
@@ -0,0 +1,50 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreProtHeap
+ *
+ * @brief Protected Heap Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/protectedheap.h>
+
+bool _Protected_heap_Walk(
+ Heap_Control *the_heap,
+ int source,
+ bool do_dump
+)
+{
+ bool status;
+
+ /*
+ * If we are called from within a dispatching critical section,
+ * then it is forbidden to lock a mutex. But since we are inside
+ * a critical section, it should be safe to walk it unlocked.
+ *
+ * NOTE: Dispatching is also disabled during initialization.
+ */
+ if ( !_Thread_Dispatch_disable_level ) {
+ _RTEMS_Lock_allocator();
+ status = _Heap_Walk( the_heap, source, do_dump );
+ _RTEMS_Unlock_allocator();
+ } else {
+ status = _Heap_Walk( the_heap, source, do_dump );
+ }
+ return status;
+}
diff --git a/cpukit/score/src/scheduler.c b/cpukit/score/src/scheduler.c
new file mode 100644
index 0000000000..71938a728c
--- /dev/null
+++ b/cpukit/score/src/scheduler.c
@@ -0,0 +1,25 @@
+/*
+ * Scheduler Handler / Initialization
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+
+void _Scheduler_Handler_initialization(void)
+{
+ (*_Scheduler.Operations.initialize)();
+}
diff --git a/cpukit/score/src/schedulerpriority.c b/cpukit/score/src/schedulerpriority.c
new file mode 100644
index 0000000000..279f42de6c
--- /dev/null
+++ b/cpukit/score/src/schedulerpriority.c
@@ -0,0 +1,33 @@
+/*
+ * Scheduler Handler
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/prioritybitmap.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+/* Instantiate any global variables needed by the priority scheduler */
+volatile Priority_bit_map_Control _Priority_Major_bit_map;
+
+Priority_bit_map_Control _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT;
+
+void _Scheduler_priority_Initialize(void)
+{
+ _Scheduler_priority_Ready_queue_initialize();
+ _Priority_bit_map_Handler_initialization();
+}
diff --git a/cpukit/score/src/schedulerpriorityallocate.c b/cpukit/score/src/schedulerpriorityallocate.c
new file mode 100644
index 0000000000..9df1e9ee5e
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityallocate.c
@@ -0,0 +1,35 @@
+/*
+ * Scheduler Priority Handler / Allocate
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/wkspace.h>
+
+void* _Scheduler_priority_Allocate (
+ Thread_Control *the_thread
+)
+{
+ void *sched;
+
+ sched = _Workspace_Allocate( sizeof(Scheduler_priority_Per_thread) );
+
+ the_thread->scheduler_info = (Scheduler_priority_Per_thread*) sched;
+
+ return sched;
+}
diff --git a/cpukit/score/src/schedulerpriorityblock.c b/cpukit/score/src/schedulerpriorityblock.c
new file mode 100644
index 0000000000..702ea48034
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityblock.c
@@ -0,0 +1,42 @@
+/*
+ * Scheduler Handler
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+
+void _Scheduler_priority_Block(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_priority_Ready_queue_extract( the_thread );
+
+ /* TODO: flash critical section? */
+
+ if ( _Thread_Is_heir( the_thread ) )
+ _Scheduler_priority_Schedule_body();
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _Thread_Dispatch_necessary = true;
+
+}
diff --git a/cpukit/score/src/schedulerpriorityenqueue.c b/cpukit/score/src/schedulerpriorityenqueue.c
new file mode 100644
index 0000000000..82e192ac8c
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityenqueue.c
@@ -0,0 +1,26 @@
+/*
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+void _Scheduler_priority_Enqueue(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_priority_Ready_queue_enqueue( the_thread );
+}
diff --git a/cpukit/score/src/schedulerpriorityenqueuefirst.c b/cpukit/score/src/schedulerpriorityenqueuefirst.c
new file mode 100644
index 0000000000..56573b7bb8
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityenqueuefirst.c
@@ -0,0 +1,27 @@
+/*
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/schedulerpriority.h>
+
+void _Scheduler_priority_Enqueue_first(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_priority_Ready_queue_enqueue_first( the_thread );
+}
+
diff --git a/cpukit/score/src/schedulerpriorityextract.c b/cpukit/score/src/schedulerpriorityextract.c
new file mode 100644
index 0000000000..83f5d28f9f
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityextract.c
@@ -0,0 +1,27 @@
+/* Scheduler Simple Handler / Extract
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/schedulerpriority.h>
+
+void _Scheduler_priority_Extract(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_priority_Ready_queue_extract( the_thread );
+}
diff --git a/cpukit/score/src/schedulerpriorityfree.c b/cpukit/score/src/schedulerpriorityfree.c
new file mode 100644
index 0000000000..27757755e3
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityfree.c
@@ -0,0 +1,29 @@
+/*
+ * Scheduler Handler
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/wkspace.h>
+
+void _Scheduler_priority_Free (
+ Thread_Control *the_thread
+)
+{
+ _Workspace_Free( the_thread->scheduler_info );
+}
diff --git a/cpukit/score/src/schedulerpriorityschedule.c b/cpukit/score/src/schedulerpriorityschedule.c
new file mode 100644
index 0000000000..e608e1f1f0
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityschedule.c
@@ -0,0 +1,25 @@
+/*
+ * Scheduler Handler / Scheduler
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+void _Scheduler_priority_Schedule(void)
+{
+ _Scheduler_priority_Schedule_body();
+}
diff --git a/cpukit/score/src/schedulerpriorityunblock.c b/cpukit/score/src/schedulerpriorityunblock.c
new file mode 100644
index 0000000000..8c0f490c8c
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityunblock.c
@@ -0,0 +1,48 @@
+/*
+ * Scheduler Handler
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+
+void _Scheduler_priority_Unblock (
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_priority_Ready_queue_enqueue(the_thread);
+
+ /* TODO: flash critical section? */
+
+ /*
+ * If the thread that was unblocked is more important than the heir,
+ * then we have a new heir. This may or may not result in a
+ * context switch.
+ *
+ * Normal case:
+ * If the current thread is preemptible, then we need to do
+ * a context switch.
+ * Pseudo-ISR case:
+ * Even if the thread isn't preemptible, if the new heir is
+ * a pseudo-ISR system task, we need to do a context switch.
+ */
+ if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
+ _Thread_Heir = the_thread;
+ if ( _Thread_Executing->is_preemptible ||
+ the_thread->current_priority == 0 )
+ _Thread_Dispatch_necessary = true;
+ }
+}
diff --git a/cpukit/score/src/schedulerpriorityupdate.c b/cpukit/score/src/schedulerpriorityupdate.c
new file mode 100644
index 0000000000..59b2432cf2
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityupdate.c
@@ -0,0 +1,42 @@
+/*
+ * Scheduler Handler
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/prioritybitmap.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+
+void _Scheduler_priority_Update(
+ Thread_Control *the_thread
+)
+{
+ Scheduler_priority_Per_thread *sched_info;
+ Chain_Control *rq;
+
+ sched_info = (Scheduler_priority_Per_thread *) the_thread->scheduler_info;
+ rq = (Chain_Control *) _Scheduler.information;
+
+ sched_info->ready_chain = &rq[ the_thread->current_priority ];
+
+ _Priority_bit_map_Initialize_information(
+ &sched_info->Priority_map,
+ the_thread->current_priority
+ );
+}
diff --git a/cpukit/score/src/schedulerpriorityyield.c b/cpukit/score/src/schedulerpriorityyield.c
new file mode 100644
index 0000000000..ba46a08f3d
--- /dev/null
+++ b/cpukit/score/src/schedulerpriorityyield.c
@@ -0,0 +1,55 @@
+/*
+ * Scheduler Priority Handler / Yield
+ *
+ * Copyright (C) 2010 Gedare Bloom.
+ * Copyright (C) 2011 On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+
+/*
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Scheduler_priority_Yield(void)
+{
+ Scheduler_priority_Per_thread *sched_info;
+ ISR_Level level;
+ Thread_Control *executing;
+ Chain_Control *ready;
+
+ executing = _Thread_Executing;
+ sched_info = (Scheduler_priority_Per_thread *) executing->scheduler_info;
+ ready = sched_info->ready_chain;
+ _ISR_Disable( level );
+ if ( !_Chain_Has_only_one_node( ready ) ) {
+ _Chain_Extract_unprotected( &executing->Object.Node );
+ _Chain_Append_unprotected( ready, &executing->Object.Node );
+
+ _ISR_Flash( level );
+
+ if ( _Thread_Is_heir( executing ) )
+ _Thread_Heir = (Thread_Control *) _Chain_First( ready );
+ _Thread_Dispatch_necessary = true;
+ }
+ else if ( !_Thread_Is_heir( executing ) )
+ _Thread_Dispatch_necessary = true;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/schedulersimple.c b/cpukit/score/src/schedulersimple.c
new file mode 100644
index 0000000000..7a7ed944f4
--- /dev/null
+++ b/cpukit/score/src/schedulersimple.c
@@ -0,0 +1,84 @@
+/*
+ * Scheduler Simple Handler / Initialize
+ * Scheduler Simple Handler / Allocate (Empty Routine)
+ * Scheduler Simple Handler / Update (Empty Routine)
+ * Scheduler Simple Handler / Free (Empty Routine)
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulersimple.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+/**
+ * This routine does nothing, and is used as a stub for Schedule allocate
+ *
+ * Note: returns a non-zero value, or else thread initialize thinks the
+ * allocation failed.
+ *
+ * The overhead of a function call will still be imposed.
+ */
+void * _Scheduler_simple_Allocate(
+ Thread_Control *the_thread
+)
+{
+ return (void*)-1; /* maybe pick an appropriate poison value */
+}
+
+
+/**
+ * This routine does nothing, and is used as a stub for Schedule update
+ *
+ * The overhead of a function call will still be imposed.
+ */
+void _Scheduler_simple_Update(
+ Thread_Control *the_thread
+)
+{
+}
+
+/**
+ * This routine does nothing, and is used as a stub for Schedule free
+ *
+ * The overhead of a function call will still be imposed.
+ */
+void _Scheduler_simple_Free(
+ Thread_Control *the_thread
+)
+{
+}
+
+/**
+ * This routine initializes the simple scheduler.
+ */
+void _Scheduler_simple_Initialize ( void )
+{
+ void *f;
+
+ /*
+ * Initialize Ready Queue
+ */
+
+ /* allocate ready queue structures */
+ f = _Workspace_Allocate_or_fatal_error( sizeof(Chain_Control) );
+ _Scheduler.information = f;
+
+ /* initialize ready queue structure */
+ _Chain_Initialize_empty( (Chain_Control *)f );
+}
diff --git a/cpukit/score/src/schedulersimpleblock.c b/cpukit/score/src/schedulersimpleblock.c
new file mode 100644
index 0000000000..212f4f10bf
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleblock.c
@@ -0,0 +1,39 @@
+/*
+ * Scheduler Simple Handler / Block
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Block(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_simple_Extract(the_thread);
+
+ if ( _Thread_Is_heir( the_thread ) )
+ _Scheduler_simple_Schedule();
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _Thread_Dispatch_necessary = true;
+}
diff --git a/cpukit/score/src/schedulersimpleenqueue.c b/cpukit/score/src/schedulersimpleenqueue.c
new file mode 100644
index 0000000000..8e5e6381c5
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleenqueue.c
@@ -0,0 +1,29 @@
+/*
+ * Schedule Simple Handler / Enqueue
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Enqueue(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_simple_Ready_queue_Enqueue( the_thread );
+}
diff --git a/cpukit/score/src/schedulersimpleenqueuefirst.c b/cpukit/score/src/schedulersimpleenqueuefirst.c
new file mode 100644
index 0000000000..d6fd7dda98
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleenqueuefirst.c
@@ -0,0 +1,28 @@
+/*
+ * Schedule Simple Handler / Enqueue First
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Enqueue_first(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_simple_Ready_queue_Enqueue_first( the_thread );
+}
diff --git a/cpukit/score/src/schedulersimpleextract.c b/cpukit/score/src/schedulersimpleextract.c
new file mode 100644
index 0000000000..208fcb55bd
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleextract.c
@@ -0,0 +1,28 @@
+/*
+ * Schedule Simple Handler / Extract
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Extract(
+ Thread_Control *the_thread
+)
+{
+ _Chain_Extract_unprotected( &the_thread->Object.Node );
+}
diff --git a/cpukit/score/src/schedulersimplereadyqueueenqueue.c b/cpukit/score/src/schedulersimplereadyqueueenqueue.c
new file mode 100644
index 0000000000..788f94b20b
--- /dev/null
+++ b/cpukit/score/src/schedulersimplereadyqueueenqueue.c
@@ -0,0 +1,48 @@
+/*
+ * Schedule Simple Handler / Ready Queue Enqueue
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Ready_queue_Enqueue(
+ Thread_Control *the_thread
+)
+{
+ Chain_Control *ready;
+ Chain_Node *the_node;
+ Thread_Control *current;
+
+ ready = (Chain_Control *)_Scheduler.information;
+ the_node = _Chain_First( ready );
+ current = (Thread_Control *)ready;
+
+ for ( ; !_Chain_Is_tail( ready, the_node ) ; the_node = the_node->next ) {
+ current = (Thread_Control *) the_node;
+
+ /* break when AT END OR PAST our priority */
+ if ( the_thread->current_priority < current->current_priority ) {
+ current = (Thread_Control *)current->Object.Node.previous;
+ break;
+ }
+ }
+
+ /* enqueue */
+ _Chain_Insert_unprotected( (Chain_Node *)current, &the_thread->Object.Node );
+}
diff --git a/cpukit/score/src/schedulersimplereadyqueueenqueuefirst.c b/cpukit/score/src/schedulersimplereadyqueueenqueuefirst.c
new file mode 100644
index 0000000000..dee0bbd116
--- /dev/null
+++ b/cpukit/score/src/schedulersimplereadyqueueenqueuefirst.c
@@ -0,0 +1,52 @@
+/*
+ * Schedule Simple Handler / Ready Queue Enqueue First
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Ready_queue_Enqueue_first(
+ Thread_Control *the_thread
+)
+{
+ Chain_Control *ready;
+ Chain_Node *the_node;
+ Thread_Control *current;
+
+ ready = (Chain_Control *)_Scheduler.information;
+ current = (Thread_Control *)ready;
+
+ /*
+ * Do NOT need to check for end of chain because there is always
+ * at least one task on the ready chain -- the IDLE task. It can
+ * never block, should never attempt to obtain a semaphore or mutex,
+ * and thus will always be there.
+ */
+ for ( the_node = _Chain_First(ready) ; ; the_node = the_node->next ) {
+ current = (Thread_Control *) the_node;
+
+ /* break when AT HEAD OF (or PAST) our priority */
+ if ( the_thread->current_priority <= current->current_priority ) {
+ current = (Thread_Control *)current->Object.Node.previous;
+ break;
+ }
+ }
+
+ /* enqueue */
+ _Chain_Insert_unprotected( (Chain_Node *)current, &the_thread->Object.Node );
+}
diff --git a/cpukit/score/src/schedulersimpleschedule.c b/cpukit/score/src/schedulersimpleschedule.c
new file mode 100644
index 0000000000..354e61f705
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleschedule.c
@@ -0,0 +1,34 @@
+/*
+ * Scheduler Simple Handler / Schedule
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Schedule(void)
+{
+ _Thread_Heir = (Thread_Control *) _Chain_First(
+ (Chain_Control *) _Scheduler.information
+ );
+}
diff --git a/cpukit/score/src/schedulersimpleunblock.c b/cpukit/score/src/schedulersimpleunblock.c
new file mode 100644
index 0000000000..5be5c16ad9
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleunblock.c
@@ -0,0 +1,47 @@
+/*
+ * Scheduler Simple Handler / Unblock
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/schedulersimple.h>
+#include <rtems/score/thread.h>
+
+void _Scheduler_simple_Unblock(
+ Thread_Control *the_thread
+)
+{
+ _Scheduler_simple_Ready_queue_Enqueue(the_thread);
+
+ /*
+ * If the thread that was unblocked is more important than the heir,
+ * then we have a new heir. This may or may not result in a
+ * context switch.
+ *
+ * Normal case:
+ * If the current thread is preemptible, then we need to do
+ * a context switch.
+ * Pseudo-ISR case:
+ * Even if the thread isn't preemptible, if the new heir is
+ * a pseudo-ISR system task, we need to do a context switch.
+ */
+ if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
+ _Thread_Heir = the_thread;
+ if ( _Thread_Executing->is_preemptible ||
+ the_thread->current_priority == 0 )
+ _Thread_Dispatch_necessary = true;
+ }
+}
diff --git a/cpukit/score/src/schedulersimpleyield.c b/cpukit/score/src/schedulersimpleyield.c
new file mode 100644
index 0000000000..61e80db7e2
--- /dev/null
+++ b/cpukit/score/src/schedulersimpleyield.c
@@ -0,0 +1,42 @@
+/*
+ * Scheduler Simple Handler / Yield
+ *
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/schedulersimple.h>
+
+void _Scheduler_simple_Yield( void )
+{
+ ISR_Level level;
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+ _ISR_Disable( level );
+
+ _Scheduler_simple_Ready_queue_Requeue(&_Scheduler, executing);
+
+ _ISR_Flash( level );
+
+ _Scheduler_simple_Schedule();
+
+ if ( !_Thread_Is_heir( executing ) )
+ _Thread_Dispatch_necessary = true;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
new file mode 100644
index 0000000000..4a0c13947f
--- /dev/null
+++ b/cpukit/score/src/smp.c
@@ -0,0 +1,153 @@
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/bspsmp.h>
+#include <rtems/score/thread.h>
+
+#if defined(RTEMS_SMP)
+#define SMP_DEBUG
+
+#if defined(SMP_DEBUG)
+ #include <rtems/bspIo.h>
+#endif
+
+void rtems_smp_run_first_task(int cpu)
+{
+ Thread_Control *heir;
+
+ /*
+ * This CPU has an heir thread so we need to dispatch it.
+ */
+ heir = _Thread_Heir;
+
+ /*
+ * This is definitely a hack until we have SMP scheduling. Since there
+ * is only one executing and heir right now, we have to fake this out.
+ */
+ _Thread_Dispatch_disable_level = 1;
+ _Thread_Executing = heir;
+ _CPU_Context_switch_to_first_task_smp( &heir->Registers );
+}
+
+void rtems_smp_secondary_cpu_initialize(void)
+{
+ int cpu;
+
+ cpu = bsp_smp_processor_id();
+
+ bsp_smp_secondary_cpu_initialize(cpu);
+
+ #if defined(SMP_DEBUG)
+ printk( "Made it to %d -- ", cpu );
+ #endif
+
+ /*
+ * Inform the primary CPU that this secondary CPU is initialized
+ * and ready to dispatch to the first thread it is supposed to
+ * execute when the primary CPU is ready.
+ */
+ _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_INITIALIZED;
+
+ /*
+ * HACK: Should not have to enable interrupts in real system here.
+ * It should happen as part of switching to the first task.
+ */
+
+ _Per_CPU_Information[cpu].isr_nest_level = 1;
+ _ISR_Set_level( 0 );
+ while(1) ;
+}
+
+void rtems_smp_process_interrupt(void)
+{
+ int cpu;
+ uint32_t message;
+ ISR_Level level;
+
+ cpu = bsp_smp_processor_id();
+
+ level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
+ message = _Per_CPU_Information[cpu].message;
+ _Per_CPU_Information[cpu].message &= ~message;
+ _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
+
+ #if defined(SMP_DEBUG)
+ {
+ void *sp = __builtin_frame_address(0);
+ if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) )
+ printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", cpu, message, sp );
+ printk( "Dispatch level %d\n", _Thread_Dispatch_disable_level );
+ }
+ #endif
+
+ if ( message & RTEMS_BSP_SMP_FIRST_TASK ) {
+ _Per_CPU_Information[cpu].isr_nest_level = 0;
+ _Per_CPU_Information[cpu].message = 0;
+ _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_INITIALIZED;
+ rtems_smp_run_first_task(cpu);
+ /* does not return */
+ }
+
+ if ( message & RTEMS_BSP_SMP_SHUTDOWN ) {
+ ISR_Level level;
+ _Thread_Dispatch_disable_level = 0;
+ _Per_CPU_Information[cpu].isr_nest_level = 0;
+ _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_SHUTDOWN;
+ _ISR_Disable( level );
+ while(1)
+ ;
+ /* does not continue past here */
+ }
+
+ if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ) {
+ printk( "switch needed\n" );
+ _Per_CPU_Information[cpu].dispatch_necessary = true;
+ }
+}
+
+void rtems_smp_send_message(
+ int cpu,
+ uint32_t message
+)
+{
+ ISR_Level level;
+
+ level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
+ _Per_CPU_Information[cpu].message |= message;
+ _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
+ bsp_smp_interrupt_cpu( cpu );
+}
+
+void rtems_smp_broadcast_message(
+ uint32_t message
+)
+{
+ int dest_cpu;
+ int cpu;
+ ISR_Level level;
+
+ cpu = bsp_smp_processor_id();
+
+ for ( dest_cpu=0 ; dest_cpu < _SMP_Processor_count; dest_cpu++ ) {
+ if ( cpu == dest_cpu )
+ continue;
+ level = _SMP_lock_Spinlock_Obtain( &_Per_CPU_Information[cpu].lock );
+ _Per_CPU_Information[dest_cpu].message |= message;
+ _SMP_lock_Spinlock_Release( &_Per_CPU_Information[cpu].lock, level );
+ }
+ bsp_smp_broadcast_interrupt();
+}
+#endif
diff --git a/cpukit/score/src/smplock.c b/cpukit/score/src/smplock.c
new file mode 100644
index 0000000000..1dd691835b
--- /dev/null
+++ b/cpukit/score/src/smplock.c
@@ -0,0 +1,49 @@
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/smplock.h>
+
+void _SMP_lock_Spinlock_Initialize(
+ SMP_lock_Control *lock
+)
+{
+ *lock = 0;
+}
+
+ISR_Level _SMP_lock_Spinlock_Obtain(
+ SMP_lock_Control *lock
+)
+{
+ ISR_Level level;
+ uint32_t value = 1;
+ uint32_t previous;
+
+ /* Note: Disable provides an implicit memory barrier. */
+ _ISR_Disable( level );
+ do {
+ SMP_CPU_SWAP( lock, value, previous );
+ } while (previous == 1);
+ return level;
+}
+
+void _SMP_lock_Spinlock_Release(
+ SMP_lock_Control *lock,
+ ISR_Level level
+)
+{
+ *lock = 0;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c
new file mode 100644
index 0000000000..7a0eb38502
--- /dev/null
+++ b/cpukit/score/src/thread.c
@@ -0,0 +1,123 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/config.h>
+
+#if defined(RTEMS_SMP)
+ #include <rtems/bspsmp.h>
+#endif
+
+/*
+ * _Thread_Handler_initialization
+ *
+ * This routine initializes all thread manager related data structures.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Handler_initialization(void)
+{
+ uint32_t ticks_per_timeslice;
+ uint32_t maximum_extensions;
+ uint32_t maximum_internal_threads;
+ #if defined(RTEMS_MULTIPROCESSING)
+ uint32_t maximum_proxies;
+ #endif
+
+ ticks_per_timeslice = Configuration.ticks_per_timeslice;
+ maximum_extensions = Configuration.maximum_extensions;
+ #if defined(RTEMS_MULTIPROCESSING)
+ maximum_proxies = _Configuration_MP_table->maximum_proxies;
+ #endif
+ /*
+ * BOTH stacks hooks must be set or both must be NULL.
+ * Do not allow mixture.
+ */
+ if ( !( (!Configuration.stack_allocate_hook)
+ == (!Configuration.stack_free_hook) ) )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_BAD_STACK_HOOK
+ );
+
+ _Thread_Dispatch_necessary = false;
+ _Thread_Executing = NULL;
+ _Thread_Heir = NULL;
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ _Thread_Allocated_fp = NULL;
+#endif
+
+ _Thread_Maximum_extensions = maximum_extensions;
+
+ _Thread_Ticks_per_timeslice = ticks_per_timeslice;
+
+ #if defined(RTEMS_MULTIPROCESSING)
+ _Thread_MP_Handler_initialization( maximum_proxies );
+ #endif
+
+ /*
+ * Initialize the internal class of threads. We need an IDLE thread
+ * per CPU in an SMP system. In addition, if this is a loosely
+ * coupled multiprocessing system, account for the MPCI Server Thread.
+ */
+ #if defined(RTEMS_SMP)
+ maximum_internal_threads = rtems_smp_maximum_processors;
+ #else
+ maximum_internal_threads = 1;
+ #endif
+
+ #if defined(RTEMS_MULTIPROCESSING)
+ if ( _System_state_Is_multiprocessing )
+ maximum_internal_threads += 1;
+ #endif
+
+ _Objects_Initialize_information(
+ &_Thread_Internal_information,
+ OBJECTS_INTERNAL_API,
+ OBJECTS_INTERNAL_THREADS,
+ maximum_internal_threads,
+ sizeof( Thread_Control ),
+ /* size of this object's control block */
+ false, /* true if names for this object are strings */
+ 8 /* maximum length of each object's name */
+ #if defined(RTEMS_MULTIPROCESSING)
+ ,
+ false, /* true if this is a global object class */
+ NULL /* Proxy extraction support callout */
+ #endif
+ );
+
+}
diff --git a/cpukit/score/src/threadblockingoperationcancel.c b/cpukit/score/src/threadblockingoperationcancel.c
new file mode 100644
index 0000000000..354df0c7e9
--- /dev/null
+++ b/cpukit/score/src/threadblockingoperationcancel.c
@@ -0,0 +1,89 @@
+/*
+ * Cancel Thread Blocking Operation
+ *
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#if defined(RTEMS_DEBUG)
+#include <rtems/score/interr.h>
+#endif
+
+void _Thread_blocking_operation_Cancel(
+#if defined(RTEMS_DEBUG)
+ Thread_blocking_operation_States sync_state,
+#else
+ Thread_blocking_operation_States sync_state __attribute__((unused)),
+#endif
+ Thread_Control *the_thread,
+ ISR_Level level
+)
+{
+ /*
+ * Cases that should not happen and why.
+ *
+ * THREAD_BLOCKING_OPERATION_SYNCHRONIZED:
+ *
+ * This indicates that someone did not enter a blocking
+ * operation critical section.
+ *
+ * THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED:
+ *
+ * This indicates that there was nothing to cancel so
+ * we should not have been called.
+ */
+
+ #if defined(RTEMS_DEBUG)
+ if ( (sync_state == THREAD_BLOCKING_OPERATION_SYNCHRONIZED) ||
+ (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) ) {
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL
+ );
+ }
+ #endif
+
+ /*
+ * The thread is not waiting on anything after this completes.
+ */
+ the_thread->Wait.queue = NULL;
+
+ /*
+ * If the sync state is timed out, this is very likely not needed.
+ * But better safe than sorry when it comes to critical sections.
+ */
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+
+}
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
new file mode 100644
index 0000000000..95011d8237
--- /dev/null
+++ b/cpukit/score/src/threadchangepriority.c
@@ -0,0 +1,99 @@
+/*
+ * Thread Handler / Change Priority
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+void _Thread_Change_priority(
+ Thread_Control *the_thread,
+ Priority_Control new_priority,
+ bool prepend_it
+)
+{
+ ISR_Level level;
+ States_Control state, original_state;
+
+ /*
+ * Save original state
+ */
+ original_state = the_thread->current_state;
+
+ /*
+ * Set a transient state for the thread so it is pulled off the Ready chains.
+ * This will prevent it from being scheduled no matter what happens in an
+ * ISR.
+ */
+ _Thread_Set_transient( the_thread );
+
+ /*
+ * Do not bother recomputing all the priority related information if
+ * we are not REALLY changing priority.
+ */
+ if ( the_thread->current_priority != new_priority )
+ _Thread_Set_priority( the_thread, new_priority );
+
+ _ISR_Disable( level );
+
+ /*
+ * If the thread has more than STATES_TRANSIENT set, then it is blocked,
+ * If it is blocked on a thread queue, then we need to requeue it.
+ */
+ state = the_thread->current_state;
+ if ( state != STATES_TRANSIENT ) {
+ /* Only clear the transient state if it wasn't set already */
+ if ( ! _States_Is_transient( original_state ) )
+ the_thread->current_state = _States_Clear( STATES_TRANSIENT, state );
+ _ISR_Enable( level );
+ if ( _States_Is_waiting_on_thread_queue( state ) ) {
+ _Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
+ }
+ return;
+ }
+
+ /* Only clear the transient state if it wasn't set already */
+ if ( ! _States_Is_transient( original_state ) ) {
+ /*
+ * Interrupts are STILL disabled.
+ * We now know the thread will be in the READY state when we remove
+ * the TRANSIENT state. So we have to place it on the appropriate
+ * Ready Queue with interrupts off.
+ */
+ the_thread->current_state = _States_Clear( STATES_TRANSIENT, state );
+
+ if ( prepend_it )
+ _Scheduler_Enqueue_first( the_thread );
+ else
+ _Scheduler_Enqueue( the_thread );
+ }
+
+ _ISR_Flash( level );
+
+ /*
+ * We altered the set of thread priorities. So let's figure out
+ * who is the heir and if we need to switch to them.
+ */
+ _Scheduler_Schedule();
+
+ if ( !_Thread_Is_executing_also_the_heir() &&
+ _Thread_Executing->is_preemptible )
+ _Thread_Dispatch_necessary = true;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadclearstate.c b/cpukit/score/src/threadclearstate.c
new file mode 100644
index 0000000000..afeab04e8e
--- /dev/null
+++ b/cpukit/score/src/threadclearstate.c
@@ -0,0 +1,58 @@
+/*
+ * Thread Handler / Thread Clear State
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * INTERRUPT LATENCY:
+ * priority map
+ * select heir
+ */
+void _Thread_Clear_state(
+ Thread_Control *the_thread,
+ States_Control state
+)
+{
+ ISR_Level level;
+ States_Control current_state;
+
+ _ISR_Disable( level );
+ current_state = the_thread->current_state;
+
+ if ( current_state & state ) {
+ current_state =
+ the_thread->current_state = _States_Clear( state, current_state );
+
+ if ( _States_Is_ready( current_state ) ) {
+ _Scheduler_Unblock( the_thread );
+ }
+ }
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadclose.c b/cpukit/score/src/threadclose.c
new file mode 100644
index 0000000000..ea2ee5bda4
--- /dev/null
+++ b/cpukit/score/src/threadclose.c
@@ -0,0 +1,104 @@
+/*
+ * Thread Handler / Thread Close
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+void _Thread_Close(
+ Objects_Information *information,
+ Thread_Control *the_thread
+)
+{
+ /*
+ * Now we are in a dispatching critical section again and we
+ * can take the thread OUT of the published set. It is invalid
+ * to use this thread's Id after this call. This will prevent
+ * any other task from attempting to initiate a call on this task.
+ */
+ _Objects_Invalidate_Id( information, &the_thread->Object );
+
+ /*
+ * We assume the Allocator Mutex is locked when we get here.
+ * This provides sufficient protection to let the user extensions
+ * run but as soon as we get back, we will make the thread
+ * disappear and set a transient state on it. So we temporarily
+ * unnest dispatching.
+ */
+ _Thread_Unnest_dispatch();
+
+ _User_extensions_Thread_delete( the_thread );
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * Now we are in a dispatching critical section again and we
+ * can take the thread OUT of the published set. It is invalid
+ * to use this thread's Id OR name after this call.
+ */
+ _Objects_Close( information, &the_thread->Object );
+
+ /*
+ * By setting the dormant state, the thread will not be considered
+ * for scheduling when we remove any blocking states.
+ */
+ _Thread_Set_state( the_thread, STATES_DORMANT );
+
+ if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) {
+ if ( _Watchdog_Is_active( &the_thread->Timer ) )
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+
+ /*
+ * Free the per-thread scheduling information.
+ */
+ _Scheduler_Free( the_thread );
+
+ /*
+ * The thread might have been FP. So deal with that.
+ */
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ if ( _Thread_Is_allocated_fp( the_thread ) )
+ _Thread_Deallocate_fp();
+#endif
+ the_thread->fp_context = NULL;
+
+ _Workspace_Free( the_thread->Start.fp_context );
+#endif
+
+ /*
+ * Free the rest of the memory associated with this task
+ * and set the associated pointers to NULL for safety.
+ */
+ _Thread_Stack_Free( the_thread );
+ the_thread->Start.stack = NULL;
+
+ _Workspace_Free( the_thread->extensions );
+ the_thread->extensions = NULL;
+}
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
new file mode 100644
index 0000000000..6a4bf65e9c
--- /dev/null
+++ b/cpukit/score/src/threadcreateidle.c
@@ -0,0 +1,106 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/config.h>
+#include <rtems/bspsmp.h>
+
+static inline void _Thread_Create_idle_helper(
+ uint32_t name_u32,
+ int cpu
+)
+{
+ Objects_Name name;
+ Thread_Control *idle;
+
+ name.name_u32 = name_u32;
+
+ /*
+ * The entire workspace is zeroed during its initialization. Thus, all
+ * fields not explicitly assigned were explicitly zeroed by
+ * _Workspace_Initialization.
+ */
+ idle = _Thread_Internal_allocate();
+
+ /*
+ * This is only called during initialization and we better be sure
+ * that when _Thread_Initialize unnests dispatch that we do not
+ * do anything stupid.
+ */
+ _Thread_Disable_dispatch();
+
+ _Thread_Initialize(
+ &_Thread_Internal_information,
+ idle,
+ NULL, /* allocate the stack */
+ _Stack_Ensure_minimum( Configuration.idle_task_stack_size ),
+ CPU_IDLE_TASK_IS_FP,
+ PRIORITY_MAXIMUM,
+ true, /* preemptable */
+ THREAD_CPU_BUDGET_ALGORITHM_NONE,
+ NULL, /* no budget algorithm callout */
+ 0, /* all interrupts enabled */
+ name
+ );
+
+ _Thread_Unnest_dispatch();
+
+ /*
+ * WARNING!!! This is necessary to "kick" start the system and
+ * MUST be done before _Thread_Start is invoked.
+ */
+ _Per_CPU_Information[ cpu ].idle =
+ _Per_CPU_Information[ cpu ].heir =
+ _Per_CPU_Information[ cpu ].executing = idle;
+
+ _Thread_Start(
+ idle,
+ THREAD_START_NUMERIC,
+ Configuration.idle_task,
+ NULL,
+ 0
+ );
+}
+
+void _Thread_Create_idle( void )
+{
+ #if defined(RTEMS_SMP)
+ int cpu;
+
+ for ( cpu=0 ; cpu < _SMP_Processor_count ; cpu++ ) {
+ _Thread_Create_idle_helper(
+ _Objects_Build_name( 'I', 'D', 'L', 'E' ),
+ cpu
+ );
+ }
+ #else
+ _Thread_Create_idle_helper(_Objects_Build_name( 'I', 'D', 'L', 'E' ), 0);
+ #endif
+}
diff --git a/cpukit/score/src/threaddelayended.c b/cpukit/score/src/threaddelayended.c
new file mode 100644
index 0000000000..4f72764608
--- /dev/null
+++ b/cpukit/score/src/threaddelayended.c
@@ -0,0 +1,71 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Delay_ended
+ *
+ * This routine processes a thread whose delay period has ended.
+ * It is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Delay_ended(
+ Objects_Id id,
+ void *ignored __attribute__((unused))
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+#if defined(RTEMS_MULTIPROCESSING)
+ case OBJECTS_REMOTE: /* impossible */
+#endif
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_Clear_state(
+ the_thread,
+ STATES_DELAYING
+ | STATES_WAITING_FOR_TIME
+ | STATES_INTERRUPTIBLE_BY_SIGNAL
+ );
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
new file mode 100644
index 0000000000..5e0828e2a6
--- /dev/null
+++ b/cpukit/score/src/threaddispatch.c
@@ -0,0 +1,193 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+#ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ #include <rtems/score/timestamp.h>
+#endif
+
+/*PAGE
+ *
+ * _Thread_Enable_dispatch
+ *
+ * This kernel routine exits a context switch disable critical section.
+ * This is the NOT INLINED version.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * dispatch thread
+ * no dispatch thread
+ */
+
+#if ( (defined(CPU_INLINE_ENABLE_DISPATCH) && \
+ (CPU_INLINE_ENABLE_DISPATCH == FALSE)) || \
+ (__RTEMS_DO_NOT_INLINE_THREAD_ENABLE_DISPATCH__ == 1) )
+void _Thread_Enable_dispatch( void )
+{
+ if ( --_Thread_Dispatch_disable_level )
+ return;
+ _Thread_Dispatch();
+}
+#endif
+
+/*PAGE
+ *
+ * _Thread_Dispatch
+ *
+ * This kernel routine determines if a dispatch is needed, and if so
+ * dispatches to the heir thread. Once the heir is running an attempt
+ * is made to dispatch any ASRs.
+ *
+ * ALTERNATE ENTRY POINTS:
+ * void _Thread_Enable_dispatch();
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * dispatch thread
+ * no dispatch thread
+ */
+
+void _Thread_Dispatch( void )
+{
+ Thread_Control *executing;
+ Thread_Control *heir;
+ ISR_Level level;
+
+ executing = _Thread_Executing;
+ _ISR_Disable( level );
+ while ( _Thread_Dispatch_necessary == true ) {
+ heir = _Thread_Heir;
+ _Thread_Dispatch_disable_level = 1;
+ _Thread_Dispatch_necessary = false;
+ _Thread_Executing = heir;
+
+ /*
+ * When the heir and executing are the same, then we are being
+ * requested to do the post switch dispatching. This is normally
+ * done to dispatch signals.
+ */
+ if ( heir == executing )
+ goto post_switch;
+
+ /*
+ * Since heir and executing are not the same, we need to do a real
+ * context switch.
+ */
+#if __RTEMS_ADA__
+ executing->rtems_ada_self = rtems_ada_self;
+ rtems_ada_self = heir->rtems_ada_self;
+#endif
+ if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
+ heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
+
+ _ISR_Enable( level );
+
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ {
+ Timestamp_Control uptime, ran;
+ _TOD_Get_uptime( &uptime );
+ _Timestamp_Subtract(
+ &_Thread_Time_of_last_context_switch,
+ &uptime,
+ &ran
+ );
+ _Timestamp_Add_to( &executing->cpu_time_used, &ran );
+ _Thread_Time_of_last_context_switch = uptime;
+ }
+ #else
+ heir->cpu_time_used++;
+ #endif
+
+ /*
+ * Switch libc's task specific data.
+ */
+ if ( _Thread_libc_reent ) {
+ executing->libc_reent = *_Thread_libc_reent;
+ *_Thread_libc_reent = heir->libc_reent;
+ }
+
+ _User_extensions_Thread_switch( executing, heir );
+
+ /*
+ * If the CPU has hardware floating point, then we must address saving
+ * and restoring it as part of the context switch.
+ *
+ * The second conditional compilation section selects the algorithm used
+ * to context switch between floating point tasks. The deferred algorithm
+ * can be significantly better in a system with few floating point tasks
+ * because it reduces the total number of save and restore FP context
+ * operations. However, this algorithm can not be used on all CPUs due
+ * to unpredictable use of FP registers by some compilers for integer
+ * operations.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
+ if ( executing->fp_context != NULL )
+ _Context_Save_fp( &executing->fp_context );
+#endif
+#endif
+
+ _Context_Switch( &executing->Registers, &heir->Registers );
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ if ( (executing->fp_context != NULL) &&
+ !_Thread_Is_allocated_fp( executing ) ) {
+ if ( _Thread_Allocated_fp != NULL )
+ _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
+ _Context_Restore_fp( &executing->fp_context );
+ _Thread_Allocated_fp = executing;
+ }
+#else
+ if ( executing->fp_context != NULL )
+ _Context_Restore_fp( &executing->fp_context );
+#endif
+#endif
+
+ executing = _Thread_Executing;
+
+ _ISR_Disable( level );
+ }
+
+post_switch:
+ _Thread_Dispatch_disable_level = 0;
+
+ _ISR_Enable( level );
+
+ _API_extensions_Run_postswitch();
+}
diff --git a/cpukit/score/src/threadget.c b/cpukit/score/src/threadget.c
new file mode 100644
index 0000000000..30574a3617
--- /dev/null
+++ b/cpukit/score/src/threadget.c
@@ -0,0 +1,100 @@
+/*
+ * Thread Handler - Object Id to Thread Pointer
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+
+/**
+ * This function maps thread IDs to thread control
+ * blocks. If ID corresponds to a local thread, then it
+ * returns the_thread control pointer which maps to ID
+ * and location is set to OBJECTS_LOCAL. If the thread ID is
+ * global and resides on a remote node, then location is set
+ * to OBJECTS_REMOTE, and the_thread is undefined.
+ * Otherwise, location is set to OBJECTS_ERROR and
+ * the_thread is undefined.
+ *
+ * @note The performance of many RTEMS services depends upon
+ * the quick execution of the "good object" path in this
+ * routine. If there is a possibility of saving a few
+ * cycles off the execution time, this routine is worth
+ * further optimization attention.
+ */
+Thread_Control *_Thread_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ uint32_t the_api;
+ uint32_t the_class;
+ Objects_Information **api_information;
+ Objects_Information *information;
+ Thread_Control *tp = (Thread_Control *) 0;
+
+ if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ) {
+ _Thread_Disable_dispatch();
+ *location = OBJECTS_LOCAL;
+ tp = _Thread_Executing;
+ goto done;
+ }
+
+ the_api = _Objects_Get_API( id );
+ if ( !_Objects_Is_api_valid( the_api ) ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ the_class = _Objects_Get_class( id );
+ if ( the_class != 1 ) { /* threads are always first class :) */
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ api_information = _Objects_Information_table[ the_api ];
+ /*
+ * There is no way for this to happen if POSIX is enabled. But there
+ * is actually a test case in sp43 for this which trips it whether or
+ * not POSIX is enabled. So in the interest of safety, this is left
+ * on in all configurations.
+ */
+ if ( !api_information ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ information = api_information[ the_class ];
+ if ( !information ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ tp = (Thread_Control *) _Objects_Get( information, id, location );
+
+done:
+ return tp;
+}
+
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
new file mode 100644
index 0000000000..37185ad745
--- /dev/null
+++ b/cpukit/score/src/threadhandler.c
@@ -0,0 +1,189 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+#if defined(__AVR__)
+ #undef __USE_INIT_FINI__
+#endif
+
+#if defined(__USE_INIT_FINI__)
+ #if defined(__M32R__)
+ #define INIT_NAME __init
+ #else
+ #define INIT_NAME _init
+ #endif
+
+ extern void INIT_NAME(void);
+ #define EXECUTE_GLOBAL_CONSTRUCTORS
+#endif
+
+#if defined(__USE__MAIN__)
+ extern void _main(void);
+ #define INIT_NAME __main
+ #define EXECUTE_GLOBAL_CONSTRUCTORS
+#endif
+
+/*PAGE
+ *
+ * _Thread_Handler
+ *
+ * This routine is the "primal" entry point for all threads.
+ * _Context_Initialize() dummies up the thread's initial context
+ * to cause the first Context_Switch() to jump to _Thread_Handler().
+ *
+ * This routine is the default thread exitted error handler. It is
+ * returned to when a thread exits. The configured fatal error handler
+ * is invoked to process the exit.
+ *
+ * NOTE:
+ *
+ * On entry, it is assumed all interrupts are blocked and that this
+ * routine needs to set the initial isr level. This may or may not
+ * actually be needed by the context switch routine and as a result
+ * interrupts may already be at there proper level. Either way,
+ * setting the initial isr level properly here is safe.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Handler( void )
+{
+ ISR_Level level;
+ Thread_Control *executing;
+ #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
+ static char doneConstructors;
+ char doneCons;
+ #endif
+
+ executing = _Thread_Executing;
+
+ /*
+ * Some CPUs need to tinker with the call frame or registers when the
+ * thread actually begins to execute for the first time. This is a
+ * hook point where the port gets a shot at doing whatever it requires.
+ */
+ _Context_Initialization_at_thread_begin();
+
+ /*
+ * have to put level into a register for those cpu's that use
+ * inline asm here
+ */
+
+ level = executing->Start.isr_level;
+ _ISR_Set_level(level);
+
+ #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
+ doneCons = doneConstructors;
+ doneConstructors = 1;
+ #endif
+
+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ #if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ if ( (executing->fp_context != NULL) &&
+ !_Thread_Is_allocated_fp( executing ) ) {
+ if ( _Thread_Allocated_fp != NULL )
+ _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
+ _Thread_Allocated_fp = executing;
+ }
+ #endif
+ #endif
+
+ /*
+ * Take care that 'begin' extensions get to complete before
+ * 'switch' extensions can run. This means must keep dispatch
+ * disabled until all 'begin' extensions complete.
+ */
+ _User_extensions_Thread_begin( executing );
+
+ /*
+ * At this point, the dispatch disable level BETTER be 1.
+ */
+ _Thread_Enable_dispatch();
+
+ #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
+ /*
+ * _init could be a weak symbol and we SHOULD test it but it isn't
+ * in any configuration I know of and it generates a warning on every
+ * RTEMS target configuration. --joel (12 May 2007)
+ */
+ if (!doneCons) /* && (volatile void *)_init) */ {
+ INIT_NAME ();
+ }
+ #endif
+
+ if ( executing->Start.prototype == THREAD_START_NUMERIC ) {
+ executing->Wait.return_argument =
+ (*(Thread_Entry_numeric) executing->Start.entry_point)(
+ executing->Start.numeric_argument
+ );
+ }
+ #if defined(RTEMS_POSIX_API)
+ else if ( executing->Start.prototype == THREAD_START_POINTER ) {
+ executing->Wait.return_argument =
+ (*(Thread_Entry_pointer) executing->Start.entry_point)(
+ executing->Start.pointer_argument
+ );
+ }
+ #endif
+ #if defined(FUNCTIONALITY_NOT_CURRENTLY_USED_BY_ANY_API)
+ else if ( executing->Start.prototype == THREAD_START_BOTH_POINTER_FIRST ) {
+ executing->Wait.return_argument =
+ (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)(
+ executing->Start.pointer_argument,
+ executing->Start.numeric_argument
+ );
+ }
+ else if ( executing->Start.prototype == THREAD_START_BOTH_NUMERIC_FIRST ) {
+ executing->Wait.return_argument =
+ (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)(
+ executing->Start.numeric_argument,
+ executing->Start.pointer_argument
+ );
+ }
+ #endif
+
+ /*
+ * In the switch above, the return code from the user thread body
+ * was placed in return_argument. This assumed that if it returned
+ * anything (which is not supporting in all APIs), then it would be
+ * able to fit in a (void *).
+ */
+
+ _User_extensions_Thread_exitted( executing );
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_THREAD_EXITTED
+ );
+}
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
new file mode 100644
index 0000000000..adb0567d14
--- /dev/null
+++ b/cpukit/score/src/threadinitialize.c
@@ -0,0 +1,242 @@
+/*
+ * Thread Handler / Thread Initialize
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Initialize
+ *
+ * This routine initializes the specified the thread. It allocates
+ * all memory associated with this thread. It completes by adding
+ * the thread to the local object table so operations on this
+ * thread id are allowed.
+ */
+
+bool _Thread_Initialize(
+ Objects_Information *information,
+ Thread_Control *the_thread,
+ void *stack_area,
+ size_t stack_size,
+ bool is_fp,
+ Priority_Control priority,
+ bool is_preemptible,
+ Thread_CPU_budget_algorithms budget_algorithm,
+ Thread_CPU_budget_algorithm_callout budget_callout,
+ uint32_t isr_level,
+ Objects_Name name
+)
+{
+ size_t actual_stack_size = 0;
+ void *stack = NULL;
+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ void *fp_area;
+ #endif
+ void *sched = NULL;
+ void *extensions_area;
+ bool extension_status;
+ int i;
+
+ /*
+ * Initialize the Ada self pointer
+ */
+ #if __RTEMS_ADA__
+ the_thread->rtems_ada_self = NULL;
+ #endif
+
+ /*
+ * Zero out all the allocated memory fields
+ */
+ for ( i=0 ; i <= THREAD_API_LAST ; i++ )
+ the_thread->API_Extensions[i] = NULL;
+
+ extensions_area = NULL;
+ the_thread->libc_reent = NULL;
+
+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ fp_area = NULL;
+ #endif
+
+ /*
+ * Allocate and Initialize the stack for this thread.
+ */
+ #if !defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
+ actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
+ if ( !actual_stack_size || actual_stack_size < stack_size )
+ return false; /* stack allocation failed */
+
+ stack = the_thread->Start.stack;
+ #else
+ if ( !stack_area ) {
+ actual_stack_size = _Thread_Stack_Allocate( the_thread, stack_size );
+ if ( !actual_stack_size || actual_stack_size < stack_size )
+ return false; /* stack allocation failed */
+
+ stack = the_thread->Start.stack;
+ the_thread->Start.core_allocated_stack = true;
+ } else {
+ stack = stack_area;
+ actual_stack_size = stack_size;
+ the_thread->Start.core_allocated_stack = false;
+ }
+ #endif
+
+ _Stack_Initialize(
+ &the_thread->Start.Initial_stack,
+ stack,
+ actual_stack_size
+ );
+
+ /*
+ * Allocate the floating point area for this thread
+ */
+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( is_fp ) {
+ fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
+ if ( !fp_area )
+ goto failed;
+ fp_area = _Context_Fp_start( fp_area, 0 );
+ }
+ the_thread->fp_context = fp_area;
+ the_thread->Start.fp_context = fp_area;
+ #endif
+
+ /*
+ * Initialize the thread timer
+ */
+ _Watchdog_Initialize( &the_thread->Timer, NULL, 0, NULL );
+
+ #ifdef __RTEMS_STRICT_ORDER_MUTEX__
+ /* Initialize the head of chain of held mutexes */
+ _Chain_Initialize_empty(&the_thread->lock_mutex);
+ #endif
+
+ /*
+ * Allocate the extensions area for this thread
+ */
+ if ( _Thread_Maximum_extensions ) {
+ extensions_area = _Workspace_Allocate(
+ (_Thread_Maximum_extensions + 1) * sizeof( void * )
+ );
+ if ( !extensions_area )
+ goto failed;
+ }
+ the_thread->extensions = (void **) extensions_area;
+
+ /*
+ * Clear the extensions area so extension users can determine
+ * if they are linked to the thread. An extension user may
+ * create the extension long after tasks have been created
+ * so they cannot rely on the thread create user extension
+ * call.
+ */
+ if ( the_thread->extensions ) {
+ for ( i = 0; i <= _Thread_Maximum_extensions ; i++ )
+ the_thread->extensions[i] = NULL;
+ }
+
+ /*
+ * General initialization
+ */
+
+ the_thread->Start.is_preemptible = is_preemptible;
+ the_thread->Start.budget_algorithm = budget_algorithm;
+ the_thread->Start.budget_callout = budget_callout;
+
+ switch ( budget_algorithm ) {
+ case THREAD_CPU_BUDGET_ALGORITHM_NONE:
+ case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
+ break;
+ #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
+ case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
+ the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
+ break;
+ #endif
+ #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
+ case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
+ break;
+ #endif
+ }
+
+ the_thread->Start.isr_level = isr_level;
+
+ the_thread->current_state = STATES_DORMANT;
+ the_thread->Wait.queue = NULL;
+ the_thread->resource_count = 0;
+ the_thread->real_priority = priority;
+ the_thread->Start.initial_priority = priority;
+ sched =_Scheduler_Allocate( the_thread );
+ if ( !sched )
+ goto failed;
+ _Thread_Set_priority( the_thread, priority );
+
+ /*
+ * Initialize the CPU usage statistics
+ */
+ #ifndef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ _Timestamp_Set_to_zero( &the_thread->cpu_time_used );
+ #else
+ the_thread->cpu_time_used = 0;
+ #endif
+
+ /*
+ * Open the object
+ */
+ _Objects_Open( information, &the_thread->Object, name );
+
+ /*
+ * We assume the Allocator Mutex is locked and dispatching is
+ * enabled when we get here. We want to be able to run the
+ * user extensions with dispatching enabled. The Allocator
+ * Mutex provides sufficient protection to let the user extensions
+ * run safely.
+ */
+ extension_status = _User_extensions_Thread_create( the_thread );
+ if ( extension_status )
+ return true;
+
+failed:
+ _Workspace_Free( the_thread->libc_reent );
+
+ for ( i=0 ; i <= THREAD_API_LAST ; i++ )
+ _Workspace_Free( the_thread->API_Extensions[i] );
+
+ _Workspace_Free( extensions_area );
+
+ #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ _Workspace_Free( fp_area );
+ #endif
+
+ _Workspace_Free( sched );
+
+ _Thread_Stack_Free( the_thread );
+ return false;
+}
diff --git a/cpukit/score/src/threadloadenv.c b/cpukit/score/src/threadloadenv.c
new file mode 100644
index 0000000000..a2d5318c78
--- /dev/null
+++ b/cpukit/score/src/threadloadenv.c
@@ -0,0 +1,74 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Load_environment
+ *
+ * Load starting environment for another thread from its start area in the
+ * thread. Only called from t_restart and t_start.
+ *
+ * Input parameters:
+ * the_thread - thread control block pointer
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Load_environment(
+ Thread_Control *the_thread
+)
+{
+ bool is_fp;
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( the_thread->Start.fp_context ) {
+ the_thread->fp_context = the_thread->Start.fp_context;
+ _Context_Initialize_fp( &the_thread->fp_context );
+ is_fp = true;
+ } else
+#endif
+ is_fp = false;
+
+ the_thread->is_preemptible = the_thread->Start.is_preemptible;
+ the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
+ the_thread->budget_callout = the_thread->Start.budget_callout;
+
+ _Context_Initialize(
+ &the_thread->Registers,
+ the_thread->Start.Initial_stack.area,
+ the_thread->Start.Initial_stack.size,
+ the_thread->Start.isr_level,
+ _Thread_Handler,
+ is_fp
+ );
+
+}
diff --git a/cpukit/score/src/threadmp.c b/cpukit/score/src/threadmp.c
new file mode 100644
index 0000000000..ffd611b4ac
--- /dev/null
+++ b/cpukit/score/src/threadmp.c
@@ -0,0 +1,168 @@
+/*
+ * Multiprocessing Support for the Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Thread_MP_Handler_initialization
+ *
+ */
+
+void _Thread_MP_Handler_initialization (
+ uint32_t maximum_proxies
+)
+{
+
+ _Chain_Initialize_empty( &_Thread_MP_Active_proxies );
+
+ if ( maximum_proxies == 0 ) {
+ _Chain_Initialize_empty( &_Thread_MP_Inactive_proxies );
+ return;
+ }
+
+
+ _Chain_Initialize(
+ &_Thread_MP_Inactive_proxies,
+ _Workspace_Allocate_or_fatal_error(
+ maximum_proxies * sizeof( Thread_Proxy_control )
+ ),
+ maximum_proxies,
+ sizeof( Thread_Proxy_control )
+ );
+
+}
+
+/*PAGE
+ *
+ * _Thread_MP_Allocate_proxy
+ *
+ */
+
+Thread_Control *_Thread_MP_Allocate_proxy (
+ States_Control the_state
+)
+{
+ Thread_Control *the_thread;
+ Thread_Proxy_control *the_proxy;
+
+ the_thread = (Thread_Control *)_Chain_Get( &_Thread_MP_Inactive_proxies );
+
+ if ( !_Thread_Is_null( the_thread ) ) {
+
+ the_proxy = (Thread_Proxy_control *) the_thread;
+
+ _Thread_Executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING;
+
+ the_proxy->receive_packet = _MPCI_Receive_server_tcb->receive_packet;
+
+ the_proxy->Object.id = _MPCI_Receive_server_tcb->receive_packet->source_tid;
+
+ the_proxy->current_priority =
+ _MPCI_Receive_server_tcb->receive_packet->source_priority;
+
+ the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
+
+ the_proxy->Wait = _Thread_Executing->Wait;
+
+ _Chain_Append( &_Thread_MP_Active_proxies, &the_proxy->Active );
+
+ return the_thread;
+ }
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_OUT_OF_PROXIES
+ );
+
+ /*
+ * NOTE: The following return ensures that the compiler will
+ * think that all paths return a value.
+ */
+
+ return NULL;
+}
+
+/*PAGE
+ *
+ * _Thread_MP_Find_proxy
+ *
+ */
+
+/*
+ * The following macro provides the offset of the Active element
+ * in the Thread_Proxy_control structure. This is the logical
+ * equivalent of the POSITION attribute in Ada.
+ */
+
+#define _Thread_MP_Proxy_Active_offset \
+ ((uint32_t)&(((Thread_Proxy_control *)0))->Active)
+
+Thread_Control *_Thread_MP_Find_proxy (
+ Objects_Id the_id
+)
+{
+
+ Chain_Node *proxy_node;
+ Thread_Control *the_thread;
+ ISR_Level level;
+
+restart:
+
+ _ISR_Disable( level );
+
+ for ( proxy_node = _Chain_First( &_Thread_MP_Active_proxies );
+ !_Chain_Is_tail( &_Thread_MP_Active_proxies, proxy_node ) ;
+ ) {
+
+ the_thread = (Thread_Control *) _Addresses_Subtract_offset(
+ proxy_node,
+ _Thread_MP_Proxy_Active_offset
+ );
+
+ if ( _Objects_Are_ids_equal( the_thread->Object.id, the_id ) ) {
+ _ISR_Enable( level );
+ return the_thread;
+ }
+
+ _ISR_Flash( level );
+
+ proxy_node = _Chain_Next( proxy_node );
+
+ /*
+ * A proxy which is only dormant is not in a blocking state.
+ * Therefore, we are looking at proxy which has been moved from
+ * active to inactive chain (by an ISR) and need to restart
+ * the search.
+ */
+
+ if ( _States_Is_only_dormant( the_thread->current_state ) ) {
+ _ISR_Enable( level );
+ goto restart;
+ }
+ }
+
+ _ISR_Enable( level );
+ return NULL;
+}
diff --git a/cpukit/score/src/threadq.c b/cpukit/score/src/threadq.c
new file mode 100644
index 0000000000..baa85a13e1
--- /dev/null
+++ b/cpukit/score/src/threadq.c
@@ -0,0 +1,66 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Initialize
+ *
+ * This routine initializes the specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * discipline - queueing discipline
+ * state - state of waiting threads
+ * timeout_status - return on a timeout
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_queue_Initialize(
+ Thread_queue_Control *the_thread_queue,
+ Thread_queue_Disciplines the_discipline,
+ States_Control state,
+ uint32_t timeout_status
+)
+{
+ the_thread_queue->state = state;
+ the_thread_queue->discipline = the_discipline;
+ the_thread_queue->timeout_status = timeout_status;
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
+
+ if ( the_discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
+ uint32_t index;
+
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++)
+ _Chain_Initialize_empty( &the_thread_queue->Queues.Priority[index] );
+ } else { /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
+ _Chain_Initialize_empty( &the_thread_queue->Queues.Fifo );
+ }
+
+}
diff --git a/cpukit/score/src/threadqdequeue.c b/cpukit/score/src/threadqdequeue.c
new file mode 100644
index 0000000000..b9213968b8
--- /dev/null
+++ b/cpukit/score/src/threadqdequeue.c
@@ -0,0 +1,72 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Dequeue
+ *
+ * This routine removes a thread from the specified threadq. If the
+ * threadq discipline is FIFO, it unblocks a thread, and cancels its
+ * timeout timer. Priority discipline is processed elsewhere.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ *
+ * Output parameters:
+ * returns - thread dequeued or NULL
+ *
+ * INTERRUPT LATENCY:
+ * check sync
+ */
+
+Thread_Control *_Thread_queue_Dequeue(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ Thread_Control *(*dequeue_p)( Thread_queue_Control * );
+ Thread_Control *the_thread;
+ ISR_Level level;
+ Thread_blocking_operation_States sync_state;
+
+ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY )
+ dequeue_p = _Thread_queue_Dequeue_priority;
+ else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
+ dequeue_p = _Thread_queue_Dequeue_fifo;
+
+ the_thread = (*dequeue_p)( the_thread_queue );
+ _ISR_Disable( level );
+ if ( !the_thread ) {
+ sync_state = the_thread_queue->sync_state;
+ if ( (sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) ||
+ (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) ) {
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
+ the_thread = _Thread_Executing;
+ }
+ }
+ _ISR_Enable( level );
+ return the_thread;
+}
diff --git a/cpukit/score/src/threadqdequeuefifo.c b/cpukit/score/src/threadqdequeuefifo.c
new file mode 100644
index 0000000000..0ea36791fc
--- /dev/null
+++ b/cpukit/score/src/threadqdequeuefifo.c
@@ -0,0 +1,79 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Dequeue_fifo
+ *
+ * This routine removes a thread from the specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ *
+ * Output parameters:
+ * returns - thread dequeued or NULL
+ *
+ * INTERRUPT LATENCY:
+ * check sync
+ * FIFO
+ */
+
+Thread_Control *_Thread_queue_Dequeue_fifo(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ ISR_Level level;
+ Thread_Control *the_thread;
+
+ _ISR_Disable( level );
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
+
+ the_thread = (Thread_Control *)
+ _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
+
+ the_thread->Wait.queue = NULL;
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+
+ return the_thread;
+ }
+
+ _ISR_Enable( level );
+ return NULL;
+}
diff --git a/cpukit/score/src/threadqdequeuepriority.c b/cpukit/score/src/threadqdequeuepriority.c
new file mode 100644
index 0000000000..1a7bc7037a
--- /dev/null
+++ b/cpukit/score/src/threadqdequeuepriority.c
@@ -0,0 +1,125 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Dequeue_priority
+ *
+ * This routine removes a thread from the specified PRIORITY based
+ * threadq, unblocks it, and cancels its timeout timer.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to thread queue
+ *
+ * Output parameters:
+ * returns - thread dequeued or NULL
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+Thread_Control *_Thread_queue_Dequeue_priority(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ uint32_t index;
+ ISR_Level level;
+ Thread_Control *the_thread = NULL; /* just to remove warnings */
+ Thread_Control *new_first_thread;
+ Chain_Node *head;
+ Chain_Node *tail;
+ Chain_Node *new_first_node;
+ Chain_Node *new_second_node;
+ Chain_Node *last_node;
+ Chain_Node *next_node;
+ Chain_Node *previous_node;
+
+ _ISR_Disable( level );
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++ ) {
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
+ the_thread = (Thread_Control *) _Chain_First(
+ &the_thread_queue->Queues.Priority[ index ]
+ );
+ goto dequeue;
+ }
+ }
+
+ /*
+ * We did not find a thread to unblock.
+ */
+ _ISR_Enable( level );
+ return NULL;
+
+dequeue:
+ the_thread->Wait.queue = NULL;
+ new_first_node = _Chain_First( &the_thread->Wait.Block2n );
+ new_first_thread = (Thread_Control *) new_first_node;
+ next_node = the_thread->Object.Node.next;
+ previous_node = the_thread->Object.Node.previous;
+
+ if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
+ last_node = _Chain_Last( &the_thread->Wait.Block2n );
+ new_second_node = new_first_node->next;
+
+ previous_node->next = new_first_node;
+ next_node->previous = new_first_node;
+ new_first_node->next = next_node;
+ new_first_node->previous = previous_node;
+
+ if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
+ /* > two threads on 2-n */
+ head = _Chain_Head( &new_first_thread->Wait.Block2n );
+ tail = _Chain_Tail( &new_first_thread->Wait.Block2n );
+
+ new_second_node->previous = head;
+ head->next = new_second_node;
+ tail->previous = last_node;
+ last_node->next = tail;
+ }
+ } else {
+ previous_node->next = next_node;
+ next_node->previous = previous_node;
+ }
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+ return( the_thread );
+}
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
new file mode 100644
index 0000000000..dbb1661feb
--- /dev/null
+++ b/cpukit/score/src/threadqenqueue.c
@@ -0,0 +1,97 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Enqueue_with_handler
+ *
+ * This routine blocks a thread, places it on a thread, and optionally
+ * starts a timeout timer.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ * timeout - interval to wait
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Thread_queue_Enqueue_with_handler(
+ Thread_queue_Control *the_thread_queue,
+ Watchdog_Interval timeout,
+ Thread_queue_Timeout_callout handler
+)
+{
+ Thread_Control *the_thread;
+ ISR_Level level;
+ Thread_blocking_operation_States sync_state;
+ Thread_blocking_operation_States (*enqueue_p)(
+ Thread_queue_Control *,
+ Thread_Control *,
+ ISR_Level *
+ );
+
+ the_thread = _Thread_Executing;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
+ the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
+ else
+#endif
+ /*
+ * Set the blocking state for this thread queue in the thread.
+ */
+ _Thread_Set_state( the_thread, the_thread_queue->state );
+
+ /*
+ * If the thread wants to timeout, then schedule its timer.
+ */
+ if ( timeout ) {
+ _Watchdog_Initialize(
+ &the_thread->Timer,
+ handler,
+ the_thread->Object.id,
+ NULL
+ );
+
+ _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
+ }
+
+ /*
+ * Now enqueue the thread per the discipline for this thread queue.
+ */
+ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY )
+ enqueue_p = _Thread_queue_Enqueue_priority;
+ else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
+ enqueue_p = _Thread_queue_Enqueue_fifo;
+
+ sync_state = (*enqueue_p)( the_thread_queue, the_thread, &level );
+ if ( sync_state != THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
+ _Thread_blocking_operation_Cancel( sync_state, the_thread, level );
+}
diff --git a/cpukit/score/src/threadqenqueuefifo.c b/cpukit/score/src/threadqenqueuefifo.c
new file mode 100644
index 0000000000..da3c809212
--- /dev/null
+++ b/cpukit/score/src/threadqenqueuefifo.c
@@ -0,0 +1,78 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Enqueue_fifo
+ *
+ * This routine places a blocked thread on a FIFO thread queue.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ * the_thread - pointer to the thread to block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+Thread_blocking_operation_States _Thread_queue_Enqueue_fifo (
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread,
+ ISR_Level *level_p
+)
+{
+ Thread_blocking_operation_States sync_state;
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ sync_state = the_thread_queue->sync_state;
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
+ if (sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED) {
+ _Chain_Append_unprotected(
+ &the_thread_queue->Queues.Fifo,
+ &the_thread->Object.Node
+ );
+ the_thread->Wait.queue = the_thread_queue;
+
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
+ _ISR_Enable( level );
+ return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+ }
+
+ /*
+ * An interrupt completed the thread's blocking request.
+ * For example, the blocking thread could have been given
+ * the mutex by an ISR or timed out.
+ *
+ * WARNING! Returning with interrupts disabled!
+ */
+ *level_p = level;
+ return sync_state;
+}
diff --git a/cpukit/score/src/threadqenqueuepriority.c b/cpukit/score/src/threadqenqueuepriority.c
new file mode 100644
index 0000000000..0d30529e0f
--- /dev/null
+++ b/cpukit/score/src/threadqenqueuepriority.c
@@ -0,0 +1,197 @@
+/*
+ * Thread Queue Handler - Enqueue By Priority
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*
+ * Support the user forcing the unrolling to be disabled.
+ */
+#if __RTEMS_DO_NOT_UNROLL_THREADQ_ENQUEUE_PRIORITY__
+ #undef CPU_UNROLL_ENQUEUE_PRIORITY
+ #define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
+#endif
+
+/*PAGE
+ *
+ * _Thread_queue_Enqueue_priority
+ *
+ * This routine places a blocked thread on a priority thread queue.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ * thread - thread to insert
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * forward less than
+ * forward equal
+ */
+
+Thread_blocking_operation_States _Thread_queue_Enqueue_priority (
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread,
+ ISR_Level *level_p
+)
+{
+ Priority_Control search_priority;
+ Thread_Control *search_thread;
+ ISR_Level level;
+ Chain_Control *header;
+ uint32_t header_index;
+ Chain_Node *the_node;
+ Chain_Node *next_node;
+ Chain_Node *previous_node;
+ Chain_Node *search_node;
+ Priority_Control priority;
+ States_Control block_state;
+
+ _Chain_Initialize_empty( &the_thread->Wait.Block2n );
+
+ priority = the_thread->current_priority;
+ header_index = _Thread_queue_Header_number( priority );
+ header = &the_thread_queue->Queues.Priority[ header_index ];
+ block_state = the_thread_queue->state;
+
+ if ( _Thread_queue_Is_reverse_search( priority ) )
+ goto restart_reverse_search;
+
+restart_forward_search:
+ search_priority = PRIORITY_MINIMUM - 1;
+ _ISR_Disable( level );
+ search_thread = (Thread_Control *) _Chain_First( header );
+ while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
+ search_priority = search_thread->current_priority;
+ if ( priority <= search_priority )
+ break;
+
+#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
+ search_thread = (Thread_Control *) search_thread->Object.Node.next;
+ if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
+ break;
+ search_priority = search_thread->current_priority;
+ if ( priority <= search_priority )
+ break;
+#endif
+ _ISR_Flash( level );
+ if ( !_States_Are_set( search_thread->current_state, block_state) ) {
+ _ISR_Enable( level );
+ goto restart_forward_search;
+ }
+ search_thread =
+ (Thread_Control *)search_thread->Object.Node.next;
+ }
+
+ if ( the_thread_queue->sync_state !=
+ THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
+ goto synchronize;
+
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
+
+ if ( priority == search_priority )
+ goto equal_priority;
+
+ search_node = (Chain_Node *) search_thread;
+ previous_node = search_node->previous;
+ the_node = (Chain_Node *) the_thread;
+
+ the_node->next = search_node;
+ the_node->previous = previous_node;
+ previous_node->next = the_node;
+ search_node->previous = the_node;
+ the_thread->Wait.queue = the_thread_queue;
+ _ISR_Enable( level );
+ return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+
+restart_reverse_search:
+ search_priority = PRIORITY_MAXIMUM + 1;
+
+ _ISR_Disable( level );
+ search_thread = (Thread_Control *) _Chain_Last( header );
+ while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
+ search_priority = search_thread->current_priority;
+ if ( priority >= search_priority )
+ break;
+#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
+ search_thread = (Thread_Control *) search_thread->Object.Node.previous;
+ if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
+ break;
+ search_priority = search_thread->current_priority;
+ if ( priority >= search_priority )
+ break;
+#endif
+ _ISR_Flash( level );
+ if ( !_States_Are_set( search_thread->current_state, block_state) ) {
+ _ISR_Enable( level );
+ goto restart_reverse_search;
+ }
+ search_thread = (Thread_Control *)
+ search_thread->Object.Node.previous;
+ }
+
+ if ( the_thread_queue->sync_state !=
+ THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED )
+ goto synchronize;
+
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
+
+ if ( priority == search_priority )
+ goto equal_priority;
+
+ search_node = (Chain_Node *) search_thread;
+ next_node = search_node->next;
+ the_node = (Chain_Node *) the_thread;
+
+ the_node->next = next_node;
+ the_node->previous = search_node;
+ search_node->next = the_node;
+ next_node->previous = the_node;
+ the_thread->Wait.queue = the_thread_queue;
+ _ISR_Enable( level );
+ return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+
+equal_priority: /* add at end of priority group */
+ search_node = _Chain_Tail( &search_thread->Wait.Block2n );
+ previous_node = search_node->previous;
+ the_node = (Chain_Node *) the_thread;
+
+ the_node->next = search_node;
+ the_node->previous = previous_node;
+ previous_node->next = the_node;
+ search_node->previous = the_node;
+ the_thread->Wait.queue = the_thread_queue;
+ _ISR_Enable( level );
+ return THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;
+
+synchronize:
+ /*
+ * An interrupt completed the thread's blocking request.
+ * For example, the blocking thread could have been given
+ * the mutex by an ISR or timed out.
+ *
+ * WARNING! Returning with interrupts disabled!
+ */
+ *level_p = level;
+ return the_thread_queue->sync_state;
+}
diff --git a/cpukit/score/src/threadqextract.c b/cpukit/score/src/threadqextract.c
new file mode 100644
index 0000000000..21aa2c2a46
--- /dev/null
+++ b/cpukit/score/src/threadqextract.c
@@ -0,0 +1,58 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract
+ *
+ * This routine removes a specific thread from the specified threadq,
+ * deletes any timeout, and unblocks the thread.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to a thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY: NONE
+ */
+
+void _Thread_queue_Extract(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+)
+{
+ /*
+ * Can not use indirect function pointer here since Extract priority
+ * is a macro and the underlying methods do not have the same signature.
+ */
+ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY )
+ _Thread_queue_Extract_priority( the_thread_queue, the_thread );
+ else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
+ _Thread_queue_Extract_fifo( the_thread_queue, the_thread );
+
+}
diff --git a/cpukit/score/src/threadqextractfifo.c b/cpukit/score/src/threadqextractfifo.c
new file mode 100644
index 0000000000..f40464d73c
--- /dev/null
+++ b/cpukit/score/src/threadqextractfifo.c
@@ -0,0 +1,78 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract_fifo
+ *
+ * This routine removes a specific thread from the specified threadq,
+ * deletes any timeout, and unblocks the thread.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to the thread to block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * EXTRACT_FIFO
+ */
+
+void _Thread_queue_Extract_fifo(
+ Thread_queue_Control *the_thread_queue __attribute__((unused)),
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ _Chain_Extract_unprotected( &the_thread->Object.Node );
+
+ the_thread->Wait.queue = NULL;
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+
+}
diff --git a/cpukit/score/src/threadqextractpriority.c b/cpukit/score/src/threadqextractpriority.c
new file mode 100644
index 0000000000..d4ddc2aa84
--- /dev/null
+++ b/cpukit/score/src/threadqextractpriority.c
@@ -0,0 +1,125 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract_priority
+ *
+ * This routine removes a specific thread from the specified threadq,
+ * deletes any timeout, and unblocks the thread.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to a thread control block
+ * requeuing - true if requeuing and should not alter timeout or state
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * EXTRACT_PRIORITY
+ */
+
+void _Thread_queue_Extract_priority_helper(
+ Thread_queue_Control *the_thread_queue __attribute__((unused)),
+ Thread_Control *the_thread,
+ bool requeuing
+)
+{
+ ISR_Level level;
+ Chain_Node *head;
+ Chain_Node *tail;
+ Chain_Node *the_node;
+ Chain_Node *next_node;
+ Chain_Node *previous_node;
+ Thread_Control *new_first_thread;
+ Chain_Node *new_first_node;
+ Chain_Node *new_second_node;
+ Chain_Node *last_node;
+
+ the_node = (Chain_Node *) the_thread;
+ _ISR_Disable( level );
+ if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ /*
+ * The thread was actually waiting on a thread queue so let's remove it.
+ */
+
+ next_node = the_node->next;
+ previous_node = the_node->previous;
+
+ if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
+ new_first_node = _Chain_First( &the_thread->Wait.Block2n );
+ new_first_thread = (Thread_Control *) new_first_node;
+ last_node = _Chain_Last( &the_thread->Wait.Block2n );
+ new_second_node = new_first_node->next;
+
+ previous_node->next = new_first_node;
+ next_node->previous = new_first_node;
+ new_first_node->next = next_node;
+ new_first_node->previous = previous_node;
+
+ if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
+ /* > two threads on 2-n */
+ head = _Chain_Head( &new_first_thread->Wait.Block2n );
+ tail = _Chain_Tail( &new_first_thread->Wait.Block2n );
+
+ new_second_node->previous = head;
+ head->next = new_second_node;
+ tail->previous = last_node;
+ last_node->next = tail;
+ }
+ } else {
+ previous_node->next = next_node;
+ next_node->previous = previous_node;
+ }
+
+ /*
+ * If we are not supposed to touch timers or the thread's state, return.
+ */
+
+ if ( requeuing ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+}
diff --git a/cpukit/score/src/threadqextractwithproxy.c b/cpukit/score/src/threadqextractwithproxy.c
new file mode 100644
index 0000000000..450702b0e4
--- /dev/null
+++ b/cpukit/score/src/threadqextractwithproxy.c
@@ -0,0 +1,67 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract_with_proxy
+ *
+ * This routine extracts the_thread from the_thread_queue
+ * and ensures that if there is a proxy for this task on
+ * another node, it is also dealt with.
+ *
+ * XXX
+ */
+
+bool _Thread_queue_Extract_with_proxy(
+ Thread_Control *the_thread
+)
+{
+ States_Control state;
+
+ state = the_thread->current_state;
+
+ if ( _States_Is_waiting_on_thread_queue( state ) ) {
+ #if defined(RTEMS_MULTIPROCESSING)
+ if ( _States_Is_waiting_for_rpc_reply( state ) &&
+ _States_Is_locally_blocked( state ) ) {
+ Objects_Information *the_information;
+ Objects_Thread_queue_Extract_callout proxy_extract_callout;
+
+ the_information = _Objects_Get_information_id( the_thread->Wait.id );
+ proxy_extract_callout =
+ (Objects_Thread_queue_Extract_callout) the_information->extract;
+
+ if ( proxy_extract_callout )
+ (*proxy_extract_callout)( the_thread );
+ }
+ #endif
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+
+ return true;
+ }
+ return false;
+}
diff --git a/cpukit/score/src/threadqfirst.c b/cpukit/score/src/threadqfirst.c
new file mode 100644
index 0000000000..8e268b87d9
--- /dev/null
+++ b/cpukit/score/src/threadqfirst.c
@@ -0,0 +1,54 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_First
+ *
+ * This routines returns a pointer to the first thread on the
+ * specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to thread queue
+ *
+ * Output parameters:
+ * returns - first thread or NULL
+ */
+
+Thread_Control *_Thread_queue_First(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ Thread_Control * (*first_p)(Thread_queue_Control *);
+
+ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY )
+ first_p = _Thread_queue_First_priority;
+ else /* must be THREAD_QUEUE_DISCIPLINE_FIFO */
+ first_p = _Thread_queue_First_fifo;
+
+ return (*first_p)( the_thread_queue );
+}
diff --git a/cpukit/score/src/threadqfirstfifo.c b/cpukit/score/src/threadqfirstfifo.c
new file mode 100644
index 0000000000..bde7b45054
--- /dev/null
+++ b/cpukit/score/src/threadqfirstfifo.c
@@ -0,0 +1,50 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_First_fifo
+ *
+ * This routines returns a pointer to the first thread on the
+ * specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ *
+ * Output parameters:
+ * returns - first thread or NULL
+ */
+
+Thread_Control *_Thread_queue_First_fifo(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
+ return (Thread_Control *) _Chain_First( &the_thread_queue->Queues.Fifo );
+
+ return NULL;
+}
diff --git a/cpukit/score/src/threadqfirstpriority.c b/cpukit/score/src/threadqfirstpriority.c
new file mode 100644
index 0000000000..e5f4bccfe4
--- /dev/null
+++ b/cpukit/score/src/threadqfirstpriority.c
@@ -0,0 +1,57 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_First_priority
+ *
+ * This routines returns a pointer to the first thread on the
+ * specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to thread queue
+ *
+ * Output parameters:
+ * returns - first thread or NULL
+ */
+
+Thread_Control *_Thread_queue_First_priority (
+ Thread_queue_Control *the_thread_queue
+)
+{
+ uint32_t index;
+
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++ ) {
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
+ return (Thread_Control *) _Chain_First(
+ &the_thread_queue->Queues.Priority[ index ]
+ );
+ }
+ return NULL;
+}
diff --git a/cpukit/score/src/threadqflush.c b/cpukit/score/src/threadqflush.c
new file mode 100644
index 0000000000..b777aa3fa1
--- /dev/null
+++ b/cpukit/score/src/threadqflush.c
@@ -0,0 +1,62 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Flush
+ *
+ * This kernel routine flushes the given thread queue.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq to be flushed
+ * remote_extract_callout - pointer to routine which extracts a remote thread
+ * status - status to return to the thread
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_queue_Flush(
+ Thread_queue_Control *the_thread_queue,
+#if defined(RTEMS_MULTIPROCESSING)
+ Thread_queue_Flush_callout remote_extract_callout,
+#else
+ Thread_queue_Flush_callout remote_extract_callout __attribute__((unused)),
+#endif
+ uint32_t status
+)
+{
+ Thread_Control *the_thread;
+
+ while ( (the_thread = _Thread_queue_Dequeue( the_thread_queue )) ) {
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ ( *remote_extract_callout )( the_thread );
+ else
+#endif
+ the_thread->Wait.return_code = status;
+ }
+}
diff --git a/cpukit/score/src/threadqprocesstimeout.c b/cpukit/score/src/threadqprocesstimeout.c
new file mode 100644
index 0000000000..9683a6e728
--- /dev/null
+++ b/cpukit/score/src/threadqprocesstimeout.c
@@ -0,0 +1,57 @@
+/*
+ * Thread Queue Handler - Process Timeout Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+void _Thread_queue_Process_timeout(
+ Thread_Control *the_thread
+)
+{
+ Thread_queue_Control *the_thread_queue = the_thread->Wait.queue;
+
+ /*
+ * If the_thread_queue is not synchronized, then it is either
+ * "nothing happened", "timeout", or "satisfied". If the_thread
+ * is the executing thread, then it is in the process of blocking
+ * and it is the thread which is responsible for the synchronization
+ * process.
+ *
+ * If it is not satisfied, then it is "nothing happened" and
+ * this is the "timeout" transition. After a request is satisfied,
+ * a timeout is not allowed to occur.
+ */
+
+ if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SYNCHRONIZED &&
+ _Thread_Is_executing( the_thread ) ) {
+ if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SATISFIED ) {
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
+ }
+ } else {
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+ }
+}
+
diff --git a/cpukit/score/src/threadqrequeue.c b/cpukit/score/src/threadqrequeue.c
new file mode 100644
index 0000000000..bba22148fb
--- /dev/null
+++ b/cpukit/score/src/threadqrequeue.c
@@ -0,0 +1,74 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Requeue
+ *
+ * This routine is invoked when a thread changes priority and should be
+ * moved to a different position on the thread queue.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to a thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY: NONE
+ */
+
+void _Thread_queue_Requeue(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+)
+{
+ /*
+ * Just in case the thread really wasn't blocked on a thread queue
+ * when we get here.
+ */
+ if ( !the_thread_queue )
+ return;
+
+ /*
+ * If queueing by FIFO, there is nothing to do. This only applies to
+ * priority blocking discipline.
+ */
+ if ( the_thread_queue->discipline == THREAD_QUEUE_DISCIPLINE_PRIORITY ) {
+ Thread_queue_Control *tq = the_thread_queue;
+ ISR_Level level;
+ ISR_Level level_ignored;
+
+ _ISR_Disable( level );
+ if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
+ _Thread_queue_Enter_critical_section( tq );
+ _Thread_queue_Extract_priority_helper( tq, the_thread, true );
+ (void) _Thread_queue_Enqueue_priority( tq, the_thread, &level_ignored );
+ }
+ _ISR_Enable( level );
+ }
+}
+
diff --git a/cpukit/score/src/threadqtimeout.c b/cpukit/score/src/threadqtimeout.c
new file mode 100644
index 0000000000..4fa1d5817b
--- /dev/null
+++ b/cpukit/score/src/threadqtimeout.c
@@ -0,0 +1,60 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*
+ * _Thread_queue_Timeout
+ *
+ * This routine processes a thread which timeouts while waiting on
+ * a thread queue. It is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_queue_Timeout(
+ Objects_Id id,
+ void *ignored __attribute__((unused))
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+#if defined(RTEMS_MULTIPROCESSING)
+ case OBJECTS_REMOTE: /* impossible */
+#endif
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_queue_Process_timeout( the_thread );
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/score/src/threadready.c b/cpukit/score/src/threadready.c
new file mode 100644
index 0000000000..9e3a285d22
--- /dev/null
+++ b/cpukit/score/src/threadready.c
@@ -0,0 +1,51 @@
+/*
+ * Thread Handler / Thread Ready
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+void _Thread_Ready(
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ the_thread->current_state = STATES_READY;
+
+ _Scheduler_Unblock( the_thread );
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadreset.c b/cpukit/score/src/threadreset.c
new file mode 100644
index 0000000000..57b5605d30
--- /dev/null
+++ b/cpukit/score/src/threadreset.c
@@ -0,0 +1,67 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Reset
+ *
+ * DESCRIPTION:
+ *
+ * This routine resets a thread to its initial stat but does
+ * not actually restart it. Some APIs do this in separate
+ * operations and this division helps support this.
+ */
+
+void _Thread_Reset(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument
+)
+{
+ the_thread->resource_count = 0;
+ the_thread->is_preemptible = the_thread->Start.is_preemptible;
+ the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
+ the_thread->budget_callout = the_thread->Start.budget_callout;
+
+ the_thread->Start.pointer_argument = pointer_argument;
+ the_thread->Start.numeric_argument = numeric_argument;
+
+ if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) {
+
+ if ( _Watchdog_Is_active( &the_thread->Timer ) )
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+
+ if ( the_thread->current_priority != the_thread->Start.initial_priority ) {
+ the_thread->real_priority = the_thread->Start.initial_priority;
+ _Thread_Set_priority( the_thread, the_thread->Start.initial_priority );
+ }
+}
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
new file mode 100644
index 0000000000..37af4d805f
--- /dev/null
+++ b/cpukit/score/src/threadrestart.c
@@ -0,0 +1,68 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Restart
+ *
+ * DESCRIPTION:
+ *
+ * This support routine restarts the specified task in a way that the
+ * next time this thread executes, it will begin execution at its
+ * original starting point.
+ */
+
+bool _Thread_Restart(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument
+)
+{
+ if ( !_States_Is_dormant( the_thread->current_state ) ) {
+
+ _Thread_Set_transient( the_thread );
+
+ _Thread_Reset( the_thread, pointer_argument, numeric_argument );
+
+ _Thread_Load_environment( the_thread );
+
+ _Thread_Ready( the_thread );
+
+ _User_extensions_Thread_restart( the_thread );
+
+ if ( _Thread_Is_executing ( the_thread ) )
+ _Thread_Restart_self();
+
+ return true;
+ }
+
+ return false;
+}
diff --git a/cpukit/score/src/threadsetpriority.c b/cpukit/score/src/threadsetpriority.c
new file mode 100644
index 0000000000..678df56fc8
--- /dev/null
+++ b/cpukit/score/src/threadsetpriority.c
@@ -0,0 +1,30 @@
+/*
+ * Thread Handler / Thread Set Priority
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/thread.h>
+
+void _Thread_Set_priority(
+ Thread_Control *the_thread,
+ Priority_Control new_priority
+)
+{
+ the_thread->current_priority = new_priority;
+
+ _Scheduler_Update( the_thread );
+}
diff --git a/cpukit/score/src/threadsetstate.c b/cpukit/score/src/threadsetstate.c
new file mode 100644
index 0000000000..1dcf33344c
--- /dev/null
+++ b/cpukit/score/src/threadsetstate.c
@@ -0,0 +1,58 @@
+/*
+ * Thread Handler / Thread Set State
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select map
+ */
+void _Thread_Set_state(
+ Thread_Control *the_thread,
+ States_Control state
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ if ( !_States_Is_ready( the_thread->current_state ) ) {
+ the_thread->current_state =
+ _States_Set( state, the_thread->current_state );
+ _ISR_Enable( level );
+ return;
+ }
+
+ the_thread->current_state = state;
+
+ _Scheduler_Block( the_thread );
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadsettransient.c b/cpukit/score/src/threadsettransient.c
new file mode 100644
index 0000000000..11f91ed30e
--- /dev/null
+++ b/cpukit/score/src/threadsettransient.c
@@ -0,0 +1,56 @@
+/*
+ * Thread Handler / Thread Set Transient
+ *
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/schedulerpriority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * INTERRUPT LATENCY:
+ * only case
+ */
+void _Thread_Set_transient(
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+ uint32_t old_state;
+
+ _ISR_Disable( level );
+
+ old_state = the_thread->current_state;
+ the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state );
+
+ if ( _States_Is_ready( old_state ) ) {
+ _Scheduler_Extract( the_thread );
+ }
+
+ _ISR_Enable( level );
+
+}
diff --git a/cpukit/score/src/threadstackallocate.c b/cpukit/score/src/threadstackallocate.c
new file mode 100644
index 0000000000..d8e21ea1f6
--- /dev/null
+++ b/cpukit/score/src/threadstackallocate.c
@@ -0,0 +1,84 @@
+/*
+ * Thread Handler - Stack Allocate Helper
+ *
+ * COPYRIGHT (c) 1989-2010.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/config.h>
+
+/*PAGE
+ *
+ * _Thread_Stack_Allocate
+ *
+ * Allocate the requested stack space for the thread.
+ * return the actual size allocated after any adjustment
+ * or return zero if the allocation failed.
+ * Set the Start.stack field to the address of the stack
+ */
+
+size_t _Thread_Stack_Allocate(
+ Thread_Control *the_thread,
+ size_t stack_size
+)
+{
+ void *stack_addr = 0;
+ size_t the_stack_size;
+
+ the_stack_size = _Stack_Ensure_minimum( stack_size );
+
+ /*
+ * Call ONLY the CPU table stack allocate hook, _or_ the
+ * the RTEMS workspace allocate. This is so the stack free
+ * routine can call the correct deallocation routine.
+ */
+
+ if ( Configuration.stack_allocate_hook ) {
+ stack_addr = (*Configuration.stack_allocate_hook)( the_stack_size );
+ } else {
+
+ /*
+ * First pad the requested size so we allocate enough memory
+ * so the context initialization can align it properly. The address
+ * returned the workspace allocate must be directly stored in the
+ * stack control block because it is later used in the free sequence.
+ *
+ * Thus it is the responsibility of the CPU dependent code to
+ * get and keep the stack adjust factor, the stack alignment, and
+ * the context initialization sequence in sync.
+ */
+
+ the_stack_size = _Stack_Adjust_size( the_stack_size );
+ stack_addr = _Workspace_Allocate( the_stack_size );
+ }
+
+ if ( !stack_addr )
+ the_stack_size = 0;
+
+ the_thread->Start.stack = stack_addr;
+
+ return the_stack_size;
+}
diff --git a/cpukit/score/src/threadstackfree.c b/cpukit/score/src/threadstackfree.c
new file mode 100644
index 0000000000..64e0278e1b
--- /dev/null
+++ b/cpukit/score/src/threadstackfree.c
@@ -0,0 +1,62 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/config.h>
+
+/*
+ * _Thread_Stack_Free
+ *
+ * Deallocate the Thread's stack.
+ */
+
+void _Thread_Stack_Free(
+ Thread_Control *the_thread
+)
+{
+ #if defined(RTEMS_SCORE_THREAD_ENABLE_USER_PROVIDED_STACK_VIA_API)
+ /*
+ * If the API provided the stack space, then don't free it.
+ */
+ if ( !the_thread->Start.core_allocated_stack )
+ return;
+ #endif
+
+ /*
+ * Call ONLY the CPU table stack free hook, or the
+ * the RTEMS workspace free. This is so the free
+ * routine properly matches the allocation of the stack.
+ */
+
+ if ( Configuration.stack_free_hook )
+ (*Configuration.stack_free_hook)( the_thread->Start.Initial_stack.area );
+ else
+ _Workspace_Free( the_thread->Start.Initial_stack.area );
+}
diff --git a/cpukit/score/src/threadstart.c b/cpukit/score/src/threadstart.c
new file mode 100644
index 0000000000..1bc293c96f
--- /dev/null
+++ b/cpukit/score/src/threadstart.c
@@ -0,0 +1,69 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Start
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the executable information for a thread
+ * and makes it ready to execute. After this routine executes, the
+ * thread competes with all other threads for CPU time.
+ */
+
+bool _Thread_Start(
+ Thread_Control *the_thread,
+ Thread_Start_types the_prototype,
+ void *entry_point,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument
+)
+{
+ if ( _States_Is_dormant( the_thread->current_state ) ) {
+
+ the_thread->Start.entry_point = (Thread_Entry) entry_point;
+
+ the_thread->Start.prototype = the_prototype;
+ the_thread->Start.pointer_argument = pointer_argument;
+ the_thread->Start.numeric_argument = numeric_argument;
+
+ _Thread_Load_environment( the_thread );
+
+ _Thread_Ready( the_thread );
+
+ _User_extensions_Thread_start( the_thread );
+
+ return true;
+ }
+
+ return false;
+}
diff --git a/cpukit/score/src/threadstartmultitasking.c b/cpukit/score/src/threadstartmultitasking.c
new file mode 100644
index 0000000000..efb2dae189
--- /dev/null
+++ b/cpukit/score/src/threadstartmultitasking.c
@@ -0,0 +1,91 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2006.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Start_multitasking
+ *
+ * This kernel routine readies the requested thread, the thread chain
+ * is adjusted. A new heir thread may be selected.
+ *
+ * Input parameters:
+ * system_thread - pointer to system initialization thread control block
+ * idle_thread - pointer to idle thread control block
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This routine uses the "blocking" heir selection mechanism.
+ * This ensures the correct heir after a thread restart.
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Start_multitasking( void )
+{
+ /*
+ * The system is now multitasking and completely initialized.
+ * This system thread now "hides" in a single processor until
+ * the system is shut down.
+ */
+
+ _System_state_Set( SYSTEM_STATE_UP );
+
+ _Thread_Dispatch_necessary = false;
+
+ _Thread_Executing = _Thread_Heir;
+
+ /*
+ * Get the init task(s) running.
+ *
+ * Note: Thread_Dispatch() is normally used to dispatch threads. As
+ * part of its work, Thread_Dispatch() restores floating point
+ * state for the heir task.
+ *
+ * This code avoids Thread_Dispatch(), and so we have to restore
+ * (actually initialize) the floating point state "by hand".
+ *
+ * Ignore the CPU_USE_DEFERRED_FP_SWITCH because we must always
+ * switch in the first thread if it is FP.
+ */
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ /*
+ * don't need to worry about saving BSP's floating point state
+ */
+
+ if ( _Thread_Heir->fp_context != NULL )
+ _Context_Restore_fp( &_Thread_Heir->fp_context );
+#endif
+
+ _Context_Switch( &_Thread_BSP_context, &_Thread_Heir->Registers );
+}
diff --git a/cpukit/score/src/threadtickletimeslice.c b/cpukit/score/src/threadtickletimeslice.c
new file mode 100644
index 0000000000..50ded7f6a7
--- /dev/null
+++ b/cpukit/score/src/threadtickletimeslice.c
@@ -0,0 +1,105 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/scheduler.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Tickle_timeslice
+ *
+ * This scheduler routine determines if timeslicing is enabled
+ * for the currently executing thread and, if so, updates the
+ * timeslice count and checks for timeslice expiration.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Tickle_timeslice( void )
+{
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+
+ #ifdef __RTEMS_USE_TICKS_FOR_STATISTICS__
+ /*
+ * Increment the number of ticks this thread has been executing
+ */
+ executing->cpu_time_used++;
+ #endif
+
+ /*
+ * If the thread is not preemptible or is not ready, then
+ * just return.
+ */
+
+ if ( !executing->is_preemptible )
+ return;
+
+ if ( !_States_Is_ready( executing->current_state ) )
+ return;
+
+ /*
+ * The cpu budget algorithm determines what happens next.
+ */
+
+ switch ( executing->budget_algorithm ) {
+ case THREAD_CPU_BUDGET_ALGORITHM_NONE:
+ break;
+
+ case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
+ #if defined(RTEMS_SCORE_THREAD_ENABLE_EXHAUST_TIMESLICE)
+ case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
+ #endif
+ if ( (int)(--executing->cpu_time_budget) <= 0 ) {
+
+ /*
+ * A yield performs the ready chain mechanics needed when
+ * resetting a timeslice. If no other thread's are ready
+ * at the priority of the currently executing thread, then the
+ * executing thread's timeslice is reset. Otherwise, the
+ * currently executing thread is placed at the rear of the
+ * FIFO for this priority and a new heir is selected.
+ */
+ _Scheduler_Yield( );
+ executing->cpu_time_budget = _Thread_Ticks_per_timeslice;
+ }
+ break;
+
+ #if defined(RTEMS_SCORE_THREAD_ENABLE_SCHEDULER_CALLOUT)
+ case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
+ if ( --executing->cpu_time_budget == 0 )
+ (*executing->budget_callout)( executing );
+ break;
+ #endif
+ }
+}
diff --git a/cpukit/score/src/timespecaddto.c b/cpukit/score/src/timespecaddto.c
new file mode 100644
index 0000000000..ac764b83c1
--- /dev/null
+++ b/cpukit/score/src/timespecaddto.c
@@ -0,0 +1,51 @@
+/**
+ * @file score/src/timespecaddto.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/**
+ *
+ * This routines adds two timespecs. The second argument is added
+ * to the first.
+ */
+
+uint32_t _Timespec_Add_to(
+ struct timespec *time,
+ const struct timespec *add
+)
+{
+ uint32_t seconds = add->tv_sec;
+
+ /* Add the basics */
+ time->tv_sec += add->tv_sec;
+ time->tv_nsec += add->tv_nsec;
+
+ /* Now adjust it so nanoseconds is in range */
+ while ( time->tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
+ time->tv_nsec -= TOD_NANOSECONDS_PER_SECOND;
+ time->tv_sec++;
+ seconds++;
+ }
+
+ return seconds;
+}
diff --git a/cpukit/score/src/timespecdivide.c b/cpukit/score/src/timespecdivide.c
new file mode 100644
index 0000000000..5e2cd2a65a
--- /dev/null
+++ b/cpukit/score/src/timespecdivide.c
@@ -0,0 +1,59 @@
+/**
+ * @file score/src/timespecdivide.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+void _Timespec_Divide(
+ const struct timespec *lhs,
+ const struct timespec *rhs,
+ uint32_t *ival_percentage,
+ uint32_t *fval_percentage
+)
+{
+ uint64_t left, right, answer;
+
+ /*
+ * For math simplicity just convert the timespec to nanoseconds
+ * in a 64-bit integer.
+ */
+ left = lhs->tv_sec * (uint64_t)TOD_NANOSECONDS_PER_SECOND;
+ left += lhs->tv_nsec;
+ right = rhs->tv_sec * (uint64_t)TOD_NANOSECONDS_PER_SECOND;
+ right += rhs->tv_nsec;
+
+ if ( right == 0 ) {
+ *ival_percentage = 0;
+ *fval_percentage = 0;
+ return;
+ }
+
+ /*
+ * Put it back in the timespec result.
+ *
+ * TODO: Rounding on the last digit of the fval.
+ */
+
+ answer = (left * 100000) / right;
+
+ *ival_percentage = answer / 1000;
+ *fval_percentage = answer % 1000;
+}
diff --git a/cpukit/score/src/timespecdividebyinteger.c b/cpukit/score/src/timespecdividebyinteger.c
new file mode 100644
index 0000000000..118fd24ee3
--- /dev/null
+++ b/cpukit/score/src/timespecdividebyinteger.c
@@ -0,0 +1,53 @@
+/**
+ * @file score/src/timespecdividebyinteger.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+void _Timespec_Divide_by_integer(
+ const struct timespec *time,
+ uint32_t iterations,
+ struct timespec *result
+)
+{
+ uint64_t t;
+
+ /*
+ * For math simplicity just convert the timespec to nanoseconds
+ * in a 64-bit integer.
+ */
+ t = time->tv_sec;
+ t *= TOD_NANOSECONDS_PER_SECOND;
+ t += time->tv_nsec;
+
+ /*
+ * Divide to get nanoseconds per iteration
+ */
+
+ t /= iterations;
+
+ /*
+ * Put it back in the timespec result
+ */
+
+ result->tv_sec = t / TOD_NANOSECONDS_PER_SECOND;
+ result->tv_nsec = t % TOD_NANOSECONDS_PER_SECOND;
+}
diff --git a/cpukit/score/src/timespecfromticks.c b/cpukit/score/src/timespecfromticks.c
new file mode 100644
index 0000000000..a3f44977fc
--- /dev/null
+++ b/cpukit/score/src/timespecfromticks.c
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+void _Timespec_From_ticks(
+ uint32_t ticks,
+ struct timespec *time
+)
+{
+ uint32_t usecs;
+
+ usecs = ticks * rtems_configuration_get_microseconds_per_tick();
+
+ time->tv_sec = usecs / TOD_MICROSECONDS_PER_SECOND;
+ time->tv_nsec = (usecs % TOD_MICROSECONDS_PER_SECOND) *
+ TOD_NANOSECONDS_PER_MICROSECOND;
+}
diff --git a/cpukit/score/src/timespecgreaterthan.c b/cpukit/score/src/timespecgreaterthan.c
new file mode 100644
index 0000000000..b0e7870ac6
--- /dev/null
+++ b/cpukit/score/src/timespecgreaterthan.c
@@ -0,0 +1,42 @@
+/**
+ * @file score/src/timespecgreaterthan.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+bool _Timespec_Greater_than(
+ const struct timespec *lhs,
+ const struct timespec *rhs
+)
+{
+ if ( lhs->tv_sec > rhs->tv_sec )
+ return true;
+
+ if ( lhs->tv_sec < rhs->tv_sec )
+ return false;
+
+ /* ASSERT: lhs->tv_sec == rhs->tv_sec */
+ if ( lhs->tv_nsec > rhs->tv_nsec )
+ return true;
+
+ return false;
+}
diff --git a/cpukit/score/src/timespecisvalid.c b/cpukit/score/src/timespecisvalid.c
new file mode 100644
index 0000000000..3347052ba9
--- /dev/null
+++ b/cpukit/score/src/timespecisvalid.c
@@ -0,0 +1,43 @@
+/**
+ * @file score/src/timespecisvalid.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+bool _Timespec_Is_valid(
+ const struct timespec *time
+)
+{
+ if ( !time )
+ return false;
+
+ if ( time->tv_sec < 0 )
+ return false;
+
+ if ( time->tv_nsec < 0 )
+ return false;
+
+ if ( time->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
+ return false;
+
+ return true;
+}
diff --git a/cpukit/score/src/timespeclessthan.c b/cpukit/score/src/timespeclessthan.c
new file mode 100644
index 0000000000..fb54e69dc9
--- /dev/null
+++ b/cpukit/score/src/timespeclessthan.c
@@ -0,0 +1,42 @@
+/**
+ * @file score/src/timespeclessthan.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+
+bool _Timespec_Less_than(
+ const struct timespec *lhs,
+ const struct timespec *rhs
+)
+{
+ if ( lhs->tv_sec < rhs->tv_sec )
+ return true;
+
+ if ( lhs->tv_sec > rhs->tv_sec )
+ return false;
+
+ /* ASSERT: lhs->tv_sec == rhs->tv_sec */
+ if ( lhs->tv_nsec < rhs->tv_nsec )
+ return true;
+
+ return false;
+}
diff --git a/cpukit/score/src/timespecsubtract.c b/cpukit/score/src/timespecsubtract.c
new file mode 100644
index 0000000000..44e9f21c25
--- /dev/null
+++ b/cpukit/score/src/timespecsubtract.c
@@ -0,0 +1,41 @@
+/**
+ * @file score/src/timespecsubtract.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+void _Timespec_Subtract(
+ const struct timespec *start,
+ const struct timespec *end,
+ struct timespec *result
+)
+{
+
+ if (end->tv_nsec < start->tv_nsec) {
+ result->tv_sec = end->tv_sec - start->tv_sec - 1;
+ result->tv_nsec =
+ (TOD_NANOSECONDS_PER_SECOND - start->tv_nsec) + end->tv_nsec;
+ } else {
+ result->tv_sec = end->tv_sec - start->tv_sec;
+ result->tv_nsec = end->tv_nsec - start->tv_nsec;
+ }
+}
diff --git a/cpukit/score/src/timespectoticks.c b/cpukit/score/src/timespectoticks.c
new file mode 100644
index 0000000000..ddd82e67a7
--- /dev/null
+++ b/cpukit/score/src/timespectoticks.c
@@ -0,0 +1,50 @@
+/**
+ * @file score/src/timespectoticks.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/timespec.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/**
+ *
+ * This routines converts a timespec to the corresponding number of ticks.
+ */
+
+uint32_t _Timespec_To_ticks(
+ const struct timespec *time
+)
+{
+ uint32_t ticks;
+
+ if ( (time->tv_sec == 0) && (time->tv_nsec == 0) )
+ return 0;
+
+ ticks = time->tv_sec * TOD_TICKS_PER_SECOND;
+
+ ticks += time->tv_nsec / rtems_configuration_get_nanoseconds_per_tick();
+
+ if (ticks)
+ return ticks;
+
+ return 1;
+}
diff --git a/cpukit/score/src/ts64addto.c b/cpukit/score/src/ts64addto.c
new file mode 100644
index 0000000000..14439de0f3
--- /dev/null
+++ b/cpukit/score/src/ts64addto.c
@@ -0,0 +1,34 @@
+/**
+ * @file score/src/ts64addto.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+void _Timestamp64_Add_to(
+ Timestamp64_Control *_time,
+ Timestamp64_Control *_add
+)
+{
+ *_time += *_add;
+}
+#endif
diff --git a/cpukit/score/src/ts64divide.c b/cpukit/score/src/ts64divide.c
new file mode 100644
index 0000000000..01e2661ac4
--- /dev/null
+++ b/cpukit/score/src/ts64divide.c
@@ -0,0 +1,52 @@
+/**
+ * @file score/src/ts64divide.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+#include <rtems/score/timestamp.h>
+
+/* This method is never inlined. */
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64)
+void _Timestamp64_Divide(
+ const Timestamp64_Control *_lhs,
+ const Timestamp64_Control *_rhs,
+ uint32_t *_ival_percentage,
+ uint32_t *_fval_percentage
+)
+{
+ Timestamp64_Control answer;
+
+ if ( *_rhs == 0 ) {
+ *_ival_percentage = 0;
+ *_fval_percentage = 0;
+ return;
+ }
+
+ /*
+ * This looks odd but gives the results the proper precision.
+ *
+ * TODO: Rounding on the last digit of the fval.
+ */
+
+ answer = (*_lhs * 100000) / *_rhs;
+
+ *_ival_percentage = answer / 1000;
+ *_fval_percentage = answer % 1000;
+}
+#endif
diff --git a/cpukit/score/src/ts64dividebyinteger.c b/cpukit/score/src/ts64dividebyinteger.c
new file mode 100644
index 0000000000..f815078322
--- /dev/null
+++ b/cpukit/score/src/ts64dividebyinteger.c
@@ -0,0 +1,35 @@
+/**
+ * @file score/src/ts64dividebyinteger.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+void _Timestamp64_Divide_by_integer(
+ Timestamp64_Control *_time,
+ uint32_t _iterations,
+ Timestamp64_Control *_result
+)
+{
+ *_result = *_time / _iterations;
+}
+#endif
diff --git a/cpukit/score/src/ts64equalto.c b/cpukit/score/src/ts64equalto.c
new file mode 100644
index 0000000000..d6c9eca998
--- /dev/null
+++ b/cpukit/score/src/ts64equalto.c
@@ -0,0 +1,34 @@
+/**
+ * @file score/src/ts64equalto.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+bool _Timestamp64_Equal_to(
+ Timestamp64_Control *_lhs,
+ Timestamp64_Control *_rhs
+)
+{
+ return (*(_lhs) == *(_rhs));
+}
+#endif
diff --git a/cpukit/score/src/ts64getnanoseconds.c b/cpukit/score/src/ts64getnanoseconds.c
new file mode 100644
index 0000000000..f9d57a9ab1
--- /dev/null
+++ b/cpukit/score/src/ts64getnanoseconds.c
@@ -0,0 +1,33 @@
+/**
+ * @file score/src/ts64toticks.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+uint32_t _Timestamp64_Get_nanoseconds(
+ Timestamp64_Control *_time
+)
+{
+ return *(_time) % 1000000000;
+}
+#endif
diff --git a/cpukit/score/src/ts64getseconds.c b/cpukit/score/src/ts64getseconds.c
new file mode 100644
index 0000000000..f459ee07a5
--- /dev/null
+++ b/cpukit/score/src/ts64getseconds.c
@@ -0,0 +1,33 @@
+/**
+ * @file score/src/ts64getseconds.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+uint32_t _Timestamp64_Get_seconds(
+ Timestamp64_Control *_time
+)
+{
+ return *(_time) / 1000000000;
+}
+#endif
diff --git a/cpukit/score/src/ts64greaterthan.c b/cpukit/score/src/ts64greaterthan.c
new file mode 100644
index 0000000000..571adca4c1
--- /dev/null
+++ b/cpukit/score/src/ts64greaterthan.c
@@ -0,0 +1,34 @@
+/**
+ * @file score/src/ts64greaterthan.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+bool _Timestamp64_Greater_than(
+ Timestamp64_Control *_lhs,
+ Timestamp64_Control *_rhs
+)
+{
+ return (*(_lhs) > *(_rhs));
+}
+#endif
diff --git a/cpukit/score/src/ts64lessthan.c b/cpukit/score/src/ts64lessthan.c
new file mode 100644
index 0000000000..1df5eb11f8
--- /dev/null
+++ b/cpukit/score/src/ts64lessthan.c
@@ -0,0 +1,34 @@
+/**
+ * @file score/src/ts64lessthan.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+bool _Timestamp64_Less_than(
+ Timestamp64_Control *_lhs,
+ Timestamp64_Control *_rhs
+)
+{
+ return (*(_lhs) < *(_rhs));
+}
+#endif
diff --git a/cpukit/score/src/ts64set.c b/cpukit/score/src/ts64set.c
new file mode 100644
index 0000000000..f4ed3c40e7
--- /dev/null
+++ b/cpukit/score/src/ts64set.c
@@ -0,0 +1,39 @@
+/**
+ * @file score/src/ts64set.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+void _Timestamp64_Set(
+ Timestamp64_Control *_time,
+ long _seconds,
+ long _nanoseconds
+)
+{
+ int64_t time;
+
+ time = (int64_t)_seconds * 1000000000;
+ time += (int64_t)_nanoseconds;
+ *_time = time;
+}
+#endif
diff --git a/cpukit/score/src/ts64settozero.c b/cpukit/score/src/ts64settozero.c
new file mode 100644
index 0000000000..f5cd78194d
--- /dev/null
+++ b/cpukit/score/src/ts64settozero.c
@@ -0,0 +1,33 @@
+/**
+ * @file score/src/ts64settozero.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+void _Timestamp64_Set_to_zero(
+ Timestamp64_Control *_time
+)
+{
+ *_time = 0;
+}
+#endif
diff --git a/cpukit/score/src/ts64subtract.c b/cpukit/score/src/ts64subtract.c
new file mode 100644
index 0000000000..be7445b2e6
--- /dev/null
+++ b/cpukit/score/src/ts64subtract.c
@@ -0,0 +1,35 @@
+/**
+ * @file score/src/ts64subtract.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+void _Timestamp64_Subtract(
+ Timestamp64_Control *_start,
+ Timestamp64_Control *_end,
+ Timestamp64_Control *_result
+)
+{
+ *_result = *_end - *_start;
+}
+#endif
diff --git a/cpukit/score/src/ts64toticks.c b/cpukit/score/src/ts64toticks.c
new file mode 100644
index 0000000000..273bcc15b4
--- /dev/null
+++ b/cpukit/score/src/ts64toticks.c
@@ -0,0 +1,40 @@
+/**
+ * @file score/src/ts64toticks.c
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/timestamp.h>
+#include <rtems/score/tod.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+uint32_t _Timestamp64_To_ticks(
+ const Timestamp64_Control *time
+)
+{
+ uint32_t ticks;
+
+ ticks = *time / rtems_configuration_get_nanoseconds_per_tick();
+ if ( ticks )
+ return ticks;
+ return 1;
+}
+#endif
diff --git a/cpukit/score/src/ts64totimespec.c b/cpukit/score/src/ts64totimespec.c
new file mode 100644
index 0000000000..92c2b690bc
--- /dev/null
+++ b/cpukit/score/src/ts64totimespec.c
@@ -0,0 +1,35 @@
+/**
+ * @file score/src/ts64totimespec.c
+*/
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/timestamp.h>
+
+#if defined(CPU_RTEMS_SCORE_TIMESTAMP_IS_INT64) && \
+ !defined(CPU_RTEMS_SCORE_TIMESTAMP_INT64_INLINE)
+void _Timestamp64_To_timespec(
+ Timestamp64_Control *_timestamp,
+ struct timespec *_timespec
+)
+{
+ _timespec->tv_sec = *_timestamp / 1000000000;
+ _timespec->tv_nsec = *_timestamp % 1000000000;
+}
+#endif
diff --git a/cpukit/score/src/userext.c b/cpukit/score/src/userext.c
new file mode 100644
index 0000000000..d0e8efc6c9
--- /dev/null
+++ b/cpukit/score/src/userext.c
@@ -0,0 +1,61 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <string.h>
+
+void _User_extensions_Handler_initialization(void)
+{
+ User_extensions_Control *extension;
+ uint32_t i;
+ uint32_t number_of_extensions;
+ User_extensions_Table *initial_extensions;
+
+ number_of_extensions = Configuration.number_of_initial_extensions;
+ initial_extensions = Configuration.User_extension_table;
+
+ _Chain_Initialize_empty( &_User_extensions_List );
+ _Chain_Initialize_empty( &_User_extensions_Switches_list );
+
+ if ( initial_extensions ) {
+ extension = (User_extensions_Control *)
+ _Workspace_Allocate_or_fatal_error(
+ number_of_extensions * sizeof( User_extensions_Control )
+ );
+
+ memset (
+ extension,
+ 0,
+ number_of_extensions * sizeof( User_extensions_Control )
+ );
+
+ for ( i = 0 ; i < number_of_extensions ; i++ ) {
+ _User_extensions_Add_set_with_table (extension, &initial_extensions[i]);
+ extension++;
+ }
+ }
+}
+
diff --git a/cpukit/score/src/userextaddset.c b/cpukit/score/src/userextaddset.c
new file mode 100644
index 0000000000..fd732e73c4
--- /dev/null
+++ b/cpukit/score/src/userextaddset.c
@@ -0,0 +1,45 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Add_set(
+ User_extensions_Control *the_extension
+)
+{
+ _Chain_Append( &_User_extensions_List, &the_extension->Node );
+
+ /*
+ * If a switch handler is present, append it to the switch chain.
+ */
+
+ if ( the_extension->Callouts.thread_switch != NULL ) {
+ the_extension->Switch.thread_switch =
+ the_extension->Callouts.thread_switch;
+ _Chain_Append(
+ &_User_extensions_Switches_list,
+ &the_extension->Switch.Node
+ );
+ }
+}
diff --git a/cpukit/score/src/userextremoveset.c b/cpukit/score/src/userextremoveset.c
new file mode 100644
index 0000000000..a7f23da536
--- /dev/null
+++ b/cpukit/score/src/userextremoveset.c
@@ -0,0 +1,39 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Remove_set (
+ User_extensions_Control *the_extension
+)
+{
+ _Chain_Extract( &the_extension->Node );
+
+ /*
+ * If a switch handler is present, remove it.
+ */
+
+ if ( the_extension->Callouts.thread_switch != NULL )
+ _Chain_Extract( &the_extension->Switch.Node );
+}
diff --git a/cpukit/score/src/userextthreadbegin.c b/cpukit/score/src/userextthreadbegin.c
new file mode 100644
index 0000000000..9fed82ac4a
--- /dev/null
+++ b/cpukit/score/src/userextthreadbegin.c
@@ -0,0 +1,81 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Thread_begin (
+ Thread_Control *executing
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_First( &_User_extensions_List );
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_begin != NULL )
+ (*the_extension->Callouts.thread_begin)( executing );
+ }
+}
+
+void _User_extensions_Thread_exitted (
+ Thread_Control *executing
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_Last( &_User_extensions_List );
+ !_Chain_Is_head( &_User_extensions_List, the_node ) ;
+ the_node = the_node->previous ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_exitted != NULL )
+ (*the_extension->Callouts.thread_exitted)( executing );
+ }
+}
+
+void _User_extensions_Fatal (
+ Internal_errors_Source the_source,
+ bool is_internal,
+ Internal_errors_t the_error
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_Last( &_User_extensions_List );
+ !_Chain_Is_head( &_User_extensions_List, the_node ) ;
+ the_node = the_node->previous ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.fatal != NULL )
+ (*the_extension->Callouts.fatal)( the_source, is_internal, the_error );
+ }
+}
diff --git a/cpukit/score/src/userextthreadcreate.c b/cpukit/score/src/userextthreadcreate.c
new file mode 100644
index 0000000000..a2950ee37e
--- /dev/null
+++ b/cpukit/score/src/userextthreadcreate.c
@@ -0,0 +1,52 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+bool _User_extensions_Thread_create (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+ bool status;
+
+ for ( the_node = _Chain_First( &_User_extensions_List );
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_create != NULL ) {
+ status = (*the_extension->Callouts.thread_create)(
+ _Thread_Executing,
+ the_thread
+ );
+ if ( !status )
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/cpukit/score/src/userextthreaddelete.c b/cpukit/score/src/userextthreaddelete.c
new file mode 100644
index 0000000000..39397fea84
--- /dev/null
+++ b/cpukit/score/src/userextthreaddelete.c
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Thread_delete (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_Last( &_User_extensions_List );
+ !_Chain_Is_head( &_User_extensions_List, the_node ) ;
+ the_node = the_node->previous ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_delete != NULL )
+ (*the_extension->Callouts.thread_delete)(
+ _Thread_Executing,
+ the_thread
+ );
+ }
+}
diff --git a/cpukit/score/src/userextthreadrestart.c b/cpukit/score/src/userextthreadrestart.c
new file mode 100644
index 0000000000..c2a4d69e6a
--- /dev/null
+++ b/cpukit/score/src/userextthreadrestart.c
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Thread_restart (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_First( &_User_extensions_List );
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_restart != NULL )
+ (*the_extension->Callouts.thread_restart)(
+ _Thread_Executing,
+ the_thread
+ );
+ }
+}
diff --git a/cpukit/score/src/userextthreadstart.c b/cpukit/score/src/userextthreadstart.c
new file mode 100644
index 0000000000..0fbe6ab755
--- /dev/null
+++ b/cpukit/score/src/userextthreadstart.c
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Thread_start (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _Chain_First( &_User_extensions_List );
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_start != NULL )
+ (*the_extension->Callouts.thread_start)(
+ _Thread_Executing,
+ the_thread
+ );
+ }
+}
diff --git a/cpukit/score/src/userextthreadswitch.c b/cpukit/score/src/userextthreadswitch.c
new file mode 100644
index 0000000000..026b56d9de
--- /dev/null
+++ b/cpukit/score/src/userextthreadswitch.c
@@ -0,0 +1,43 @@
+/**
+ * @file
+ *
+ * @ingroup ScoreUserExt
+ *
+ * @brief User Extension Handler implementation.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2007.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+void _User_extensions_Thread_switch (
+ Thread_Control *executing,
+ Thread_Control *heir
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Switch_control *the_extension_switch;
+
+ for ( the_node = _Chain_First( &_User_extensions_Switches_list );
+ !_Chain_Is_tail( &_User_extensions_Switches_list, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension_switch = (User_extensions_Switch_control *) the_node;
+
+ (*the_extension_switch->thread_switch)( executing, heir );
+ }
+}
diff --git a/cpukit/score/src/watchdog.c b/cpukit/score/src/watchdog.c
new file mode 100644
index 0000000000..591f2de117
--- /dev/null
+++ b/cpukit/score/src/watchdog.c
@@ -0,0 +1,42 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Handler_initialization
+ *
+ * This routine initializes the watchdog handler.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Watchdog_Handler_initialization( void )
+{
+ _Watchdog_Sync_count = 0;
+ _Watchdog_Sync_level = 0;
+ _Watchdog_Ticks_since_boot = 0;
+
+ _Chain_Initialize_empty( &_Watchdog_Ticks_chain );
+ _Chain_Initialize_empty( &_Watchdog_Seconds_chain );
+}
diff --git a/cpukit/score/src/watchdogadjust.c b/cpukit/score/src/watchdogadjust.c
new file mode 100644
index 0000000000..89d4859906
--- /dev/null
+++ b/cpukit/score/src/watchdogadjust.c
@@ -0,0 +1,87 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Adjust
+ *
+ * This routine adjusts the delta chain backward or forward in response
+ * to a time change.
+ *
+ * Input parameters:
+ * header - pointer to the delta chain to be adjusted
+ * direction - forward or backward adjustment to delta chain
+ * units - units to adjust
+ *
+ * Output parameters:
+ */
+
+void _Watchdog_Adjust(
+ Chain_Control *header,
+ Watchdog_Adjust_directions direction,
+ Watchdog_Interval units
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ /*
+ * NOTE: It is safe NOT to make 'header' a pointer
+ * to volatile data (contrast this with watchdoginsert.c)
+ * because we call _Watchdog_Tickle() below and
+ * hence the compiler must not assume *header to remain
+ * unmodified across that call.
+ *
+ * Till Straumann, 7/2003
+ */
+ if ( !_Chain_Is_empty( header ) ) {
+ switch ( direction ) {
+ case WATCHDOG_BACKWARD:
+ _Watchdog_First( header )->delta_interval += units;
+ break;
+ case WATCHDOG_FORWARD:
+ while ( units ) {
+ if ( units < _Watchdog_First( header )->delta_interval ) {
+ _Watchdog_First( header )->delta_interval -= units;
+ break;
+ } else {
+ units -= _Watchdog_First( header )->delta_interval;
+ _Watchdog_First( header )->delta_interval = 1;
+
+ _ISR_Enable( level );
+
+ _Watchdog_Tickle( header );
+
+ _ISR_Disable( level );
+
+ if ( _Chain_Is_empty( header ) )
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ _ISR_Enable( level );
+
+}
diff --git a/cpukit/score/src/watchdogadjusttochain.c b/cpukit/score/src/watchdogadjusttochain.c
new file mode 100644
index 0000000000..569a9364f7
--- /dev/null
+++ b/cpukit/score/src/watchdogadjusttochain.c
@@ -0,0 +1,83 @@
+/**
+ * @file watchdogadjusttochain.c
+ *
+ * This is used by the Timer Server task.
+ */
+
+/* COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+void _Watchdog_Adjust_to_chain(
+ Chain_Control *header,
+ Watchdog_Interval units_arg,
+ Chain_Control *to_fire
+
+)
+{
+ Watchdog_Interval units = units_arg;
+ ISR_Level level;
+ Watchdog_Control *first;
+
+ if ( units <= 0 ) {
+ return;
+ }
+
+ _ISR_Disable( level );
+
+ while ( 1 ) {
+ if ( units <= 0 ) {
+ break;
+ }
+ if ( _Chain_Is_empty( header ) ) {
+ break;
+ }
+ first = _Watchdog_First( header );
+
+ /*
+ * If it is longer than "units" until the first element on the chain
+ * fires, then bump it and quit.
+ */
+ if ( units < first->delta_interval ) {
+ first->delta_interval -= units;
+ break;
+ }
+
+ /*
+ * The first set happens in less than units, so take all of them
+ * off the chain and adjust units to reflect this.
+ */
+ units -= first->delta_interval;
+ first->delta_interval = 0;
+
+ while ( 1 ) {
+ _Chain_Extract_unprotected( &first->Node );
+ _Chain_Append_unprotected( to_fire, &first->Node );
+
+ _ISR_Flash( level );
+
+ if ( _Chain_Is_empty( header ) )
+ break;
+ first = _Watchdog_First( header );
+ if ( first->delta_interval != 0 )
+ break;
+ }
+ }
+
+ _ISR_Enable( level );
+}
+
diff --git a/cpukit/score/src/watchdoginsert.c b/cpukit/score/src/watchdoginsert.c
new file mode 100644
index 0000000000..e4b86bd271
--- /dev/null
+++ b/cpukit/score/src/watchdoginsert.c
@@ -0,0 +1,100 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Insert
+ *
+ * This routine inserts a watchdog timer on to the appropriate delta
+ * chain while updating the delta interval counters.
+ */
+
+void _Watchdog_Insert(
+ Chain_Control *header,
+ Watchdog_Control *the_watchdog
+)
+{
+ ISR_Level level;
+ Watchdog_Control *after;
+ uint32_t insert_isr_nest_level;
+ Watchdog_Interval delta_interval;
+
+
+ insert_isr_nest_level = _ISR_Nest_level;
+
+ _ISR_Disable( level );
+
+ /*
+ * Check to see if the watchdog has just been inserted by a
+ * higher priority interrupt. If so, abandon this insert.
+ */
+
+ if ( the_watchdog->state != WATCHDOG_INACTIVE ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ the_watchdog->state = WATCHDOG_BEING_INSERTED;
+ _Watchdog_Sync_count++;
+
+restart:
+ delta_interval = the_watchdog->initial;
+
+ for ( after = _Watchdog_First( header ) ;
+ ;
+ after = _Watchdog_Next( after ) ) {
+
+ if ( delta_interval == 0 || !_Watchdog_Next( after ) )
+ break;
+
+ if ( delta_interval < after->delta_interval ) {
+ after->delta_interval -= delta_interval;
+ break;
+ }
+
+ delta_interval -= after->delta_interval;
+
+ _ISR_Flash( level );
+
+ if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
+ goto exit_insert;
+ }
+
+ if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
+ _Watchdog_Sync_level = insert_isr_nest_level;
+ goto restart;
+ }
+ }
+
+ _Watchdog_Activate( the_watchdog );
+
+ the_watchdog->delta_interval = delta_interval;
+
+ _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
+
+ the_watchdog->start_time = _Watchdog_Ticks_since_boot;
+
+exit_insert:
+ _Watchdog_Sync_level = insert_isr_nest_level;
+ _Watchdog_Sync_count--;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/watchdognanoseconds.c b/cpukit/score/src/watchdognanoseconds.c
new file mode 100644
index 0000000000..b3d3e7b028
--- /dev/null
+++ b/cpukit/score/src/watchdognanoseconds.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+
+Watchdog_Nanoseconds_since_last_tick_routine
+ _Watchdog_Nanoseconds_since_tick_handler =
+ _Watchdog_Nanoseconds_since_tick_default_handler;
+
+uint32_t _Watchdog_Nanoseconds_since_tick_default_handler( void )
+{
+ return 0;
+}
diff --git a/cpukit/score/src/watchdogremove.c b/cpukit/score/src/watchdogremove.c
new file mode 100644
index 0000000000..3ce3367657
--- /dev/null
+++ b/cpukit/score/src/watchdogremove.c
@@ -0,0 +1,73 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Remove
+ *
+ * The routine removes a watchdog from a delta chain and updates
+ * the delta counters of the remaining watchdogs.
+ */
+
+Watchdog_States _Watchdog_Remove(
+ Watchdog_Control *the_watchdog
+)
+{
+ ISR_Level level;
+ Watchdog_States previous_state;
+ Watchdog_Control *next_watchdog;
+
+ _ISR_Disable( level );
+ previous_state = the_watchdog->state;
+ switch ( previous_state ) {
+ case WATCHDOG_INACTIVE:
+ break;
+
+ case WATCHDOG_BEING_INSERTED:
+
+ /*
+ * It is not actually on the chain so just change the state and
+ * the Insert operation we interrupted will be aborted.
+ */
+ the_watchdog->state = WATCHDOG_INACTIVE;
+ break;
+
+ case WATCHDOG_ACTIVE:
+ case WATCHDOG_REMOVE_IT:
+
+ the_watchdog->state = WATCHDOG_INACTIVE;
+ next_watchdog = _Watchdog_Next( the_watchdog );
+
+ if ( _Watchdog_Next(next_watchdog) )
+ next_watchdog->delta_interval += the_watchdog->delta_interval;
+
+ if ( _Watchdog_Sync_count )
+ _Watchdog_Sync_level = _ISR_Nest_level;
+
+ _Chain_Extract_unprotected( &the_watchdog->Node );
+ break;
+ }
+ the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
+
+ _ISR_Enable( level );
+ return( previous_state );
+}
diff --git a/cpukit/score/src/watchdogreport.c b/cpukit/score/src/watchdogreport.c
new file mode 100644
index 0000000000..58bce56959
--- /dev/null
+++ b/cpukit/score/src/watchdogreport.c
@@ -0,0 +1,41 @@
+/**
+ * @file watchdogreport.c
+ *
+ * This should only be used for debugging.
+ */
+
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/bspIo.h>
+
+void _Watchdog_Report(
+ const char *name,
+ Watchdog_Control *watch
+)
+{
+ printk(
+ "%s%s%4d %5d %p %p 0x%08x %p\n",
+ ((name) ? name : ""),
+ ((name) ? " " : ""),
+ watch->delta_interval,
+ watch->initial,
+ watch,
+ watch->routine,
+ watch->id,
+ watch->user_data
+ );
+}
diff --git a/cpukit/score/src/watchdogreportchain.c b/cpukit/score/src/watchdogreportchain.c
new file mode 100644
index 0000000000..8b616914c6
--- /dev/null
+++ b/cpukit/score/src/watchdogreportchain.c
@@ -0,0 +1,50 @@
+/**
+ * @file watchdogreportchain.c
+ *
+ * This should only be used for debugging.
+ */
+
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/isr.h>
+#include <rtems/bspIo.h>
+
+void _Watchdog_Report_chain(
+ const char *name,
+ Chain_Control *header
+)
+{
+ ISR_Level level;
+ Chain_Node *node;
+
+ _ISR_Disable( level );
+ printk( "Watchdog Chain: %s %p\n", name, header );
+ if ( !_Chain_Is_empty( header ) ) {
+ for ( node = _Chain_First( header ) ;
+ node != _Chain_Tail(header) ;
+ node = node->next )
+ {
+ Watchdog_Control *watch = (Watchdog_Control *) node;
+
+ _Watchdog_Report( NULL, watch );
+ }
+ printk( "== end of %s \n", name );
+ } else {
+ printk( "Chain is empty\n" );
+ }
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/watchdogtickle.c b/cpukit/score/src/watchdogtickle.c
new file mode 100644
index 0000000000..09b3c7bf09
--- /dev/null
+++ b/cpukit/score/src/watchdogtickle.c
@@ -0,0 +1,129 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Tickle
+ *
+ * This routine decrements the delta counter in response to a tick. The
+ * delta chain is updated accordingly.
+ *
+ * Input parameters:
+ * header - pointer to the delta chain to be tickled
+ *
+ * Output parameters: NONE
+ */
+
+void _Watchdog_Tickle(
+ Chain_Control *header
+)
+{
+ ISR_Level level;
+ Watchdog_Control *the_watchdog;
+ Watchdog_States watchdog_state;
+
+ /*
+ * See the comment in watchdoginsert.c and watchdogadjust.c
+ * about why it's safe not to declare header a pointer to
+ * volatile data - till, 2003/7
+ */
+
+ _ISR_Disable( level );
+
+ if ( _Chain_Is_empty( header ) )
+ goto leave;
+
+ the_watchdog = _Watchdog_First( header );
+
+ /*
+ * For some reason, on rare occasions the_watchdog->delta_interval
+ * of the head of the watchdog chain is 0. Before this test was
+ * added, on these occasions an event (which usually was supposed
+ * to have a timeout of 1 tick would have a delta_interval of 0, which
+ * would be decremented to 0xFFFFFFFF by the unprotected
+ * "the_watchdog->delta_interval--;" operation.
+ * This would mean the event would not timeout, and also the chain would
+ * be blocked, because a timeout with a very high number would be at the
+ * head, rather than at the end.
+ * The test "if (the_watchdog->delta_interval != 0)"
+ * here prevents this from occuring.
+ *
+ * We were not able to categorically identify the situation that causes
+ * this, but proved it to be true empirically. So this check causes
+ * correct behaviour in this circumstance.
+ *
+ * The belief is that a race condition exists whereby an event at the head
+ * of the chain is removed (by a pending ISR or higher priority task)
+ * during the _ISR_Flash( level ); in _Watchdog_Insert, but the watchdog
+ * to be inserted has already had its delta_interval adjusted to 0, and
+ * so is added to the head of the chain with a delta_interval of 0.
+ *
+ * Steven Johnson - 12/2005 (gcc-3.2.3 -O3 on powerpc)
+ */
+ if (the_watchdog->delta_interval != 0) {
+ the_watchdog->delta_interval--;
+ if ( the_watchdog->delta_interval != 0 )
+ goto leave;
+ }
+
+ do {
+ watchdog_state = _Watchdog_Remove( the_watchdog );
+
+ _ISR_Enable( level );
+
+ switch( watchdog_state ) {
+ case WATCHDOG_ACTIVE:
+ (*the_watchdog->routine)(
+ the_watchdog->id,
+ the_watchdog->user_data
+ );
+ break;
+
+ case WATCHDOG_INACTIVE:
+ /*
+ * This state indicates that the watchdog is not on any chain.
+ * Thus, it is NOT on a chain being tickled. This case should
+ * never occur.
+ */
+ break;
+
+ case WATCHDOG_BEING_INSERTED:
+ /*
+ * This state indicates that the watchdog is in the process of
+ * BEING inserted on the chain. Thus, it can NOT be on a chain
+ * being tickled. This case should never occur.
+ */
+ break;
+
+ case WATCHDOG_REMOVE_IT:
+ break;
+ }
+
+ _ISR_Disable( level );
+
+ the_watchdog = _Watchdog_First( header );
+ } while ( !_Chain_Is_empty( header ) &&
+ (the_watchdog->delta_interval == 0) );
+
+leave:
+ _ISR_Enable(level);
+}
diff --git a/cpukit/score/src/wkspace.c b/cpukit/score/src/wkspace.c
new file mode 100644
index 0000000000..568bfc1ce7
--- /dev/null
+++ b/cpukit/score/src/wkspace.c
@@ -0,0 +1,125 @@
+/*
+ * Workspace Handler
+ *
+ * COPYRIGHT (c) 1989-2009.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/interr.h>
+
+#include <string.h> /* for memset */
+
+/* #define DEBUG_WORKSPACE */
+#if defined(DEBUG_WORKSPACE)
+ #include <rtems/bspIo.h>
+#endif
+
+/*
+ * _Workspace_Handler_initialization
+ */
+void _Workspace_Handler_initialization(void)
+{
+ uintptr_t memory_available = 0;
+ void *starting_address = Configuration.work_space_start;
+ uintptr_t size = Configuration.work_space_size;
+
+ if ( Configuration.do_zero_of_workspace )
+ memset( starting_address, 0, size );
+
+ memory_available = _Heap_Initialize(
+ &_Workspace_Area,
+ starting_address,
+ size,
+ CPU_HEAP_ALIGNMENT
+ );
+
+ if ( memory_available == 0 )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
+ );
+}
+
+/*
+ * _Workspace_Allocate
+ */
+void *_Workspace_Allocate(
+ size_t size
+)
+{
+ void *memory;
+
+ memory = _Heap_Allocate( &_Workspace_Area, size );
+ #if defined(DEBUG_WORKSPACE)
+ printk(
+ "Workspace_Allocate(%d) from %p/%p -> %p\n",
+ size,
+ __builtin_return_address( 0 ),
+ __builtin_return_address( 1 ),
+ memory
+ );
+ #endif
+ return memory;
+}
+
+/*
+ * _Workspace_Free
+ */
+void _Workspace_Free(
+ void *block
+)
+{
+ #if defined(DEBUG_WORKSPACE)
+ printk(
+ "Workspace_Free(%p) from %p/%p\n",
+ block,
+ __builtin_return_address( 0 ),
+ __builtin_return_address( 1 )
+ );
+ #endif
+ _Heap_Free( &_Workspace_Area, block );
+}
+
+/*
+ * _Workspace_Allocate_or_fatal_error
+ */
+void *_Workspace_Allocate_or_fatal_error(
+ size_t size
+)
+{
+ void *memory;
+
+ memory = _Heap_Allocate( &_Workspace_Area, size );
+ #if defined(DEBUG_WORKSPACE)
+ printk(
+ "Workspace_Allocate_or_fatal_error(%d) from %p/%p -> %p\n",
+ size,
+ __builtin_return_address( 0 ),
+ __builtin_return_address( 1 ),
+ memory
+ );
+ #endif
+
+ if ( memory == NULL )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ true,
+ INTERNAL_ERROR_WORKSPACE_ALLOCATION
+ );
+
+ return memory;
+}