Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 8525)
+++ wp-includes/post.php	(working copy)
@@ -482,6 +482,8 @@
 	} elseif ( ! empty($r['exclude']) )
 		$r['post__not_in'] = preg_split('/[\s,]+/',$r['exclude']);
 
+	$r['caller_get_posts'] = true;
+
 	$get_posts = new WP_Query;
 	return $get_posts->query($r);
 
@@ -750,6 +752,30 @@
 }
 
 /**
+ * is_sticky() - Check if post is sticky
+ *
+ * {@internal Missing Long Description}}
+ *
+ * @package WordPress
+ * @subpackage Post
+ * @since 2.7
+ *
+ * @param int $post_id A post ID
+ * @return bool
+ */
+function is_sticky($post_id) {
+	$stickies = get_option('sticky_posts');
+
+	if ( !is_array($stickies) )
+		return false;
+
+	if ( in_array($post_id, $stickies) )
+		return true;
+
+	return false;
+}
+
+/**
  * sanitize_post() - Sanitize every post field
  *
  * {@internal Missing Long Description}}
@@ -847,6 +873,36 @@
 	return $value;
 }
 
+function stick_post($post_id) {
+	$stickies = get_option('sticky_posts');
+
+	if ( !is_array($stickies) )
+		$stickies = array($post_id);
+
+	if ( ! in_array($post_id, $stickies) )
+		$stickies[] = $post_id;
+
+	update_option('sticky_posts', $stickies);
+}
+
+function unstick_post($post_id) {
+	$stickies = get_option('sticky_posts');
+
+	if ( !is_array($stickies) )
+		return;
+
+	if ( ! in_array($post_id, $stickies) )
+		return;
+
+	$offset = array_search($post_id, $stickies);
+	if ( false === $offset )
+		return;
+
+	array_splice($stickies, $offset, 1);
+	
+	update_option('sticky_posts', $stickies);
+}
+
 /**
  * Count number of posts of a post type and is user has permissions to view.
  *
Index: wp-includes/query.php
===================================================================
--- wp-includes/query.php	(revision 8525)
+++ wp-includes/query.php	(working copy)
@@ -831,6 +831,9 @@
 		$groupby = '';
 		$post_status_join = false;
 
+		if ( !isset($q['caller_get_posts']) )
+			$q['caller_get_posts'] = false;
+
 		if ( !isset($q['post_type']) ) {
 			if ( $this->is_search )
 				$q['post_type'] = 'any';
@@ -1460,6 +1463,37 @@
 			$this->comment_count = count($this->comments);
 		}
 
+		// Put sticky posts at the top of the posts array
+		$sticky_posts = get_option('sticky_posts');
+		if ( $this->is_home && $page <= 1 && !empty($sticky_posts) && !$q['caller_get_posts'] ) {
+			$num_posts = count($this->posts);
+			$post_ids = array();
+			$sticky_offset = 0;
+			// Loop over posts and relocate stickies to the front.
+			for ( $i = 0; $i < $num_posts; $i++ ) {
+				if ( in_array($this->posts[$i]->ID, $sticky_posts) ) {
+					$sticky_post = $this->posts[$i];
+					// Remove sticky from current position
+					array_splice($this->posts, $i, 1);
+					// Move to front, after other stickies
+					array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
+					//Increment the sticky offset.  The next sticky goes here.
+					$sticky_offset++;
+					// Remove post from sticky posts array
+					$offset = array_search($sticky_post->ID, $sticky_posts);
+					array_splice($sticky_posts, $offset, 1);
+				}
+			}
+
+			// Fetch sticky posts that weren't in the query results
+			// TODO Fetch all posts with one query
+			foreach ( $sticky_posts as $sticky_post ) {
+				$sticky_post = get_post($sticky_post);
+				array_splice($this->posts, $sticky_offset, 0, array($sticky_post));
+				$sticky_offset++;
+			}
+		}
+
 		if ( !empty($limits) ) {
 			$found_posts_query = apply_filters( 'found_posts_query', 'SELECT FOUND_ROWS()' );
 			$this->found_posts = $wpdb->get_var( $found_posts_query );
