diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index aa77b31c593f78c20d661969feaba1ae7139c582..b85768e5e5dd06af6252ebb883c294d3ec63c2d0 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -83,8 +83,6 @@ Drupal 7.0, xxxx-xx-xx (development version)
     * Revamped the filter API and text format storage.
     * Added support for default text formats to be assigned on a per-role basis.
     * Refactored the HTML corrector to take advantage of PHP 5 features.
-- Removed ping module:
-    * Contributed modules with similar functionality are available.
 - User system:
     * Added clean API functions for creating, loading, updating, and deleting
       user roles and permissions.
@@ -96,9 +94,6 @@ Drupal 7.0, xxxx-xx-xx (development version)
       at the operating system level.
     * Removed per-user themes: Contributed modules with similar functionality
       are available.
-- Removed throttle module:
-    * Alternative methods for improving performance are available in other core and
-      contributed modules.
 - Added code registry:
     * Using the registry, modules declare their includable files via their .info file,
       allowing Drupal to lazy-load classes and interfaces as needed.
@@ -173,10 +168,14 @@ Drupal 7.0, xxxx-xx-xx (development version)
     * Upgraded the jQuery Forms library to 2.21.
     * Added jQuery UI 1.7.2, which allows improvements to Drupal's user
       experience.
-- Better module version support.
+- Better module version support
     * Modules now can specify which version of another module they depend on.
-- Blog API
-    * This module has been removed from core.
+- Removed modules from core
+    * The following modules have been removed from core, because contributed
+      modules with similar functionality are available:
+      * Blog API module
+      * Ping module
+      * Throttle module
 - Improved node access control system.
     * All modules may now influence the access to a node at runtime, not just
       the module that defined a node.
@@ -188,6 +187,11 @@ Drupal 7.0, xxxx-xx-xx (development version)
     * Simplified definitions of actions and triggers.
     * Removed dependency on the combination of hooks and operations. Triggers
       now directly map to module hooks.
+- Task handling
+    * Added a queue API to process many or long-running tasks.
+    * Added queue API support to cron API.
+    * Added a locking framework to coordinate long-running operations across
+      requests.
 
 Drupal 6.0, 2008-02-13
 ----------------------
diff --git a/modules/system/system.api.php b/modules/system/system.api.php
index 67a3d3d56f9c0c8b928eb3f040674094813ab5e0..559d64761a45b93645dcfd1ef47112c9a042d137 100644
--- a/modules/system/system.api.php
+++ b/modules/system/system.api.php
@@ -120,25 +120,48 @@ function hook_entity_info_alter(&$entity_info) {
 /**
  * Perform periodic actions.
  *
+ * This hook will only be called if cron.php is run (e.g. by crontab).
+ *
  * Modules that require to schedule some commands to be executed at regular
  * intervals can implement hook_cron(). The engine will then call the hook
  * at the appropriate intervals defined by the administrator. This interface
  * is particularly handy to implement timers or to automate certain tasks.
  * Database maintenance, recalculation of settings or parameters are good
  * candidates for cron tasks.
- * Long running tasks should use the queue API, define one or more queues with
- * hook_cron_queue_info() and put items in the queue instead of running them in
- * hook_cron(). Examples of jobs that are good candidates for hook_cron_queue_info
- * include automated mailing, retrieving remote data, and intensive file tasks.
  *
- * This hook will only be called if cron.php is run (e.g. by crontab).
+ * Short-running or not resource intensive tasks can be executed directly.
+ *
+ * Long-running tasks should use the queue API. To do this, one or more queues
+ * need to be defined via hook_cron_queue_info(). Items that need to be
+ * processed are appended to the defined queue, instead of processing them
+ * directly in hook_cron().
+ * Examples of jobs that are good candidates for
+ * hook_cron_queue_info() include automated mailing, retrieving remote data, and
+ * intensive file tasks.
+ *
+ * @return
+ *   None.
+ *
+ * @see hook_cron_queue_info()
  */
 function hook_cron() {
-  $result = db_query('SELECT * FROM {site} WHERE checked = 0 OR checked + refresh < :time', array(':time' => REQUEST_TIME));
-  $queue = DrupalQueue::get('aggregator_feeds');
+  // Short-running operation example, not using a queue:
+  // Delete all expired records since the last cron run.
+  $expires = variable_get('mymodule_cron_last_run', REQUEST_TIME);
+  db_delete('mymodule_table')
+    ->condition('expires', $expires, '>=')
+    ->execute();
+  variable_set('mymodule_cron_last_run', REQUEST_TIME);
 
-  foreach ($result as $site) {
-    $queue->createItem($site);
+  // Long-running operation example, leveraging a queue:
+  // Fetch feeds from other sites.
+  $result = db_query('SELECT * FROM {aggregator_feed} WHERE checked + refresh < :time AND refresh != :never', array(
+    ':time' => REQUEST_TIME,
+    ':never' => AGGREGATOR_CLEAR_NEVER,
+  ));
+  $queue = DrupalQueue::get('aggregator_feeds');
+  foreach ($result as $feed) {
+    $queue->createItem($feed);
   }
 }
 
@@ -148,18 +171,20 @@ function hook_cron() {
  * While there can be only one hook_cron() process running at the same time,
  * there can be any number of processes defined here running. Because of
  * this, long running tasks are much better suited for this API. Items queued
- * in hook_cron might be processed in the same cron run if there are not many
- * items in the queue, otherwise it might take several requests.which can be run
- * in parallel.
+ * in hook_cron() might be processed in the same cron run if there are not many
+ * items in the queue, otherwise it might take several requests, which can be
+ * run in parallel.
  *
  * @return
  *   An associative array where the key is the queue name and the value is
  *   again an associative array. Possible keys are:
- *     'worker callback'  The name of the function to call. It will be called
- *                        with one argument, the $item from createItem called
- *                        in hook_cron.
- *     'time'             How much time Drupal should spend on calling this
- *                        worker in seconds. Optional, defaults to 15.
+ *   - 'worker callback': The name of the function to call. It will be called
+ *     with one argument, the item created via DrupalQueue::createItem() in
+ *     hook_cron().
+ *   - 'time': (optional) How much time Drupal should spend on calling this
+ *     worker in seconds. Defaults to 15.
+ *
+ * @see hook_cron()
  */
 function hook_cron_queue_info() {
   $queues['aggregator_feeds'] = array(
@@ -703,8 +728,11 @@ function hook_mail_alter(&$message) {
  * @param $file
  *   Full information about the module or theme, including $file->name, and
  *   $file->filename
+ * @param $type
+ *   Either 'module' or 'theme', depending on the type of .info file that was
+ *   passed.
  */
-function hook_system_info_alter(&$info, $file) {
+function hook_system_info_alter(&$info, $file, $type) {
   // Only fill this in if the .info file does not define a 'datestamp'.
   if (empty($info['datestamp'])) {
     $info['datestamp'] = filemtime($file->filename);
diff --git a/modules/system/system.module b/modules/system/system.module
index fa308f81b9d97cbe44502393e9844bd42697190b..b8ff23d7717055029fd30cbf6015670e80e7a6c4 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -1895,7 +1895,7 @@ function _system_get_module_data() {
 
     // Invoke hook_system_info_alter() to give installed modules a chance to
     // modify the data in the .info files if necessary.
-    drupal_alter('system_info', $modules[$key]->info, $modules[$key]);
+    drupal_alter('system_info', $modules[$key]->info, $modules[$key], 'module');
   }
 
   // The install profile is required.
@@ -1988,7 +1988,7 @@ function _system_get_theme_data() {
 
       // Invoke hook_system_info_alter() to give installed modules a chance to
       // modify the data in the .info files if necessary.
-      drupal_alter('system_info', $themes[$key]->info, $themes[$key]);
+      drupal_alter('system_info', $themes[$key]->info, $themes[$key], 'theme');
 
       if (!empty($themes[$key]->info['base theme'])) {
         $sub_themes[] = $key;
@@ -2150,11 +2150,13 @@ function system_region_list($theme_key, $show = REGIONS_ALL) {
 /**
  * Implement hook_system_info_alter().
  */
-function system_system_info_alter(&$info, $file) {
+function system_system_info_alter(&$info, $file, $type) {
   // Remove page-top from the blocks UI since it is reserved for modules to
   // populate from outside the blocks system.
-  $info['regions_hidden'][] = 'page_top';
-  $info['regions_hidden'][] = 'page_bottom';
+  if ($type == 'theme') {
+    $info['regions_hidden'][] = 'page_top';
+    $info['regions_hidden'][] = 'page_bottom';
+  }
 }
 
 /**