jcs ratpoison hax
at jcs 337 lines 8.1 kB view raw
1/* This file was taken from the Linux kernel and is 2 * Copyright (C) 2003 Linus Torvalds 3 * 4 * Modified by Shawn Betts. Portions created by Shawn Betts are 5 * Copyright (C) 2003, 2004 Shawn Betts 6 * 7 * This file is part of ratpoison. 8 * 9 * ratpoison is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2, or (at your option) 12 * any later version. 13 * 14 * ratpoison is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this software; see the file COPYING. If not, write to 21 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 22 * Boston, MA 02111-1307 USA 23 */ 24 25#include "linkedlist.h" 26 27/* 28 * Insert a new entry between two known consecutive entries. 29 * 30 * This is only for internal list manipulation where we know 31 * the prev/next entries already! 32 */ 33void 34__list_add(struct list_head *new, 35 struct list_head *prev, 36 struct list_head *next) 37{ 38 next->prev = new; 39 new->next = next; 40 new->prev = prev; 41 prev->next = new; 42} 43 44/** 45 * list_add - add a new entry 46 * @new: new entry to be added 47 * @head: list head to add it after 48 * 49 * Insert a new entry after the specified head. 50 * This is good for implementing stacks. 51 */ 52void 53list_add(struct list_head *new, struct list_head *head) 54{ 55 __list_add(new, head, head->next); 56} 57 58/** 59 * list_add_tail - add a new entry 60 * @new: new entry to be added 61 * @head: list head to add it before 62 * 63 * Insert a new entry before the specified head. 64 * This is useful for implementing queues. 65 */ 66void 67list_add_tail(struct list_head *new, struct list_head *head) 68{ 69 __list_add(new, head->prev, head); 70} 71 72/* 73 * Delete a list entry by making the prev/next entries 74 * point to each other. 75 * 76 * This is only for internal list manipulation where we know 77 * the prev/next entries already! 78 */ 79void 80__list_del(struct list_head * prev, struct list_head * next) 81{ 82 next->prev = prev; 83 prev->next = next; 84} 85 86/** 87 * list_del - deletes entry from list. 88 * @entry: the element to delete from the list. 89 * Note: list_empty on entry does not return true after this, the entry is 90 * in an undefined state. 91 */ 92void 93list_del(struct list_head *entry) 94{ 95 __list_del(entry->prev, entry->next); 96} 97 98/** 99 * list_del_init - deletes entry from list and reinitialize it. 100 * @entry: the element to delete from the list. 101 */ 102void 103list_del_init(struct list_head *entry) 104{ 105 __list_del(entry->prev, entry->next); 106 INIT_LIST_HEAD(entry); 107} 108 109/** 110 * list_move - delete from one list and add as another's head 111 * @list: the entry to move 112 * @head: the head that will precede our entry 113 */ 114void 115list_move(struct list_head *list, struct list_head *head) 116{ 117 __list_del(list->prev, list->next); 118 list_add(list, head); 119} 120 121/** 122 * list_move_tail - delete from one list and add as another's tail 123 * @list: the entry to move 124 * @head: the head that will follow our entry 125 */ 126void 127list_move_tail(struct list_head *list, 128 struct list_head *head) 129{ 130 __list_del(list->prev, list->next); 131 list_add_tail(list, head); 132} 133 134/** 135 * list_empty - tests whether a list is empty 136 * @head: the list to test. 137 */ 138int 139list_empty(struct list_head *head) 140{ 141 return head->next == head; 142} 143 144void 145__list_splice(struct list_head *list, 146 struct list_head *head) 147{ 148 struct list_head *first = list->next; 149 struct list_head *last = list->prev; 150 struct list_head *at = head->next; 151 152 first->prev = head; 153 head->next = first; 154 155 last->next = at; 156 at->prev = last; 157} 158 159/** 160 * list_splice - join two lists 161 * @list: the new list to add. 162 * @head: the place to add it in the first list. 163 */ 164void 165list_splice(struct list_head *list, struct list_head *head) 166{ 167 if (!list_empty(list)) 168 __list_splice(list, head); 169} 170 171/** 172 * list_splice_init - join two lists and reinitialise the emptied list. 173 * @list: the new list to add. 174 * @head: the place to add it in the first list. 175 * 176 * The list at @list is reinitialised 177 */ 178void 179list_splice_init(struct list_head *list, 180 struct list_head *head) 181{ 182 if (!list_empty(list)) { 183 __list_splice(list, head); 184 INIT_LIST_HEAD(list); 185 } 186} 187 188int 189list_size (struct list_head *list) 190{ 191 struct list_head *cur; 192 193 int i = 0; 194 list_for_each (cur, list) 195 i++; 196 197 return i; 198} 199 200#define MAX_LIST_LENGTH_BITS 20 201#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) 202 203/* 204 * Returns a list organized in an intermediate format suited 205 * to chaining of merge() calls: null-terminated, no reserved or 206 * sentinel head node, "prev" links not maintained. 207 */ 208static struct list_head * 209merge(void *priv, 210 int (*cmp)(void *priv, struct list_head *a, 211 struct list_head *b), 212 struct list_head *a, struct list_head *b) 213{ 214 struct list_head head, *tail = &head; 215 216 while (a && b) { 217 /* if equal, take 'a' -- important for sort stability */ 218 if ((*cmp) (priv, a, b) <= 0) { 219 tail->next = a; 220 a = a->next; 221 } else { 222 tail->next = b; 223 b = b->next; 224 } 225 tail = tail->next; 226 } 227 tail->next = a?:b; 228 return head.next; 229} 230 231/* 232 * Combine final list merge with restoration of standard doubly-linked 233 * list structure. This approach duplicates code from merge(), but 234 * runs faster than the tidier alternatives of either a separate final 235 * prev-link restoration pass, or maintaining the prev links 236 * throughout. 237 */ 238static void 239merge_and_restore_back_links(void *priv, 240 int (*cmp)(void *priv, struct list_head *a, 241 struct list_head *b), 242 struct list_head *head, 243 struct list_head *a, struct list_head *b) 244{ 245 struct list_head *tail = head; 246 unsigned int count = 0; 247 248 while (a && b) { 249 /* if equal, take 'a' -- important for sort stability */ 250 if ((*cmp) (priv, a, b) <= 0) { 251 tail->next = a; 252 a->prev = tail; 253 a = a->next; 254 } else { 255 tail->next = b; 256 b->prev = tail; 257 b = b->next; 258 } 259 tail = tail->next; 260 } 261 tail->next = a ? : b; 262 263 do { 264 /* 265 * In worst cases this loop may run many iterations. 266 * Continue callbacks to the client even though no 267 * element comparison is needed, so the client's cmp() 268 * routine can invoke cond_resched() periodically. 269 */ 270 if (!(++count)) 271 (*cmp) (priv, tail->next, tail->next); 272 273 tail->next->prev = tail; 274 tail = tail->next; 275 } while (tail->next); 276 277 tail->next = head; 278 head->prev = tail; 279} 280 281/** 282 * list_sort - sort a list 283 * @priv: private data, opaque to list_sort(), passed to @cmp 284 * @head: the list to sort 285 * @cmp: the elements comparison function 286 * 287 * This function implements "merge sort", which has O(nlog(n)) 288 * complexity. 289 * 290 * The comparison function @cmp must return a negative value if @a 291 * should sort before @b, and a positive value if @a should sort after 292 * @b. If @a and @b are equivalent, and their original relative 293 * ordering is to be preserved, @cmp must return 0. 294 */ 295void 296list_sort(void *priv, struct list_head *head, 297 int (*cmp)(void *priv, struct list_head *a, 298 struct list_head *b)) 299{ 300 struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists 301 -- last slot is a sentinel */ 302 int lev; /* index into part[] */ 303 int max_lev = 0; 304 struct list_head *list; 305 306 if (list_empty (head)) 307 return; 308 309 memset(part, 0, sizeof(part)); 310 311 head->prev->next = NULL; 312 list = head->next; 313 314 while (list) { 315 struct list_head *cur = list; 316 list = list->next; 317 cur->next = NULL; 318 319 for (lev = 0; part[lev]; lev++) { 320 cur = merge (priv, cmp, part[lev], cur); 321 part[lev] = NULL; 322 } 323 if (lev > max_lev) { 324 if (lev >= ARRAY_SIZE(part)-1) { 325 lev--; 326 } 327 max_lev = lev; 328 } 329 part[lev] = cur; 330 } 331 332 for (lev = 0; lev < max_lev; lev++) 333 if (part[lev]) 334 list = merge (priv, cmp, part[lev], list); 335 336 merge_and_restore_back_links (priv, cmp, head, part[max_lev], list); 337}