Ditto for hash_elem.
implement priority scheduling in problem 1-3 (@pxref{Problem 1-3
Priority Scheduling}).
-@item list_elem elem;
+@item struct list_elem elem;
A ``list element'' used to put the thread into doubly linked lists,
either the list of threads ready to run or a list of threads waiting
on a semaphore. Take a look at @file{lib/kernel/list.h} for
@anchor{Hash Table}
@b{How do I use the hash table provided in @file{lib/kernel/hash.c}?}
-First, you need to embed a @code{hash_elem} object as a member of the
-object that the hash table will contain. Each @code{hash_elem} allows
+First, you need to embed a @struct{hash_elem} as a member of the
+object that the hash table will contain. Each @struct{hash_elem} allows
the object to a member of at most one hash table at a given time. All
the hash table functions that deal with hash table items actually use
-the address of a @code{hash_elem}. You can convert a pointer to a
-@code{hash_elem} member into a pointer to the structure in which
+the address of a @struct{hash_elem}. You can convert a pointer to a
+@struct{hash_elem} member into a pointer to the structure in which
member is embedded using the @code{hash_entry} macro.
Second, you need to decide on a key type. The key should be something
@code{hash_less_func} in @file{lib/kernel/hash.h}.
Here's a quick example. Suppose you want to put @struct{thread}s
-in a hash table. First, add a @code{hash_elem} to the thread
+in a hash table. First, add a @struct{hash_elem} to the thread
structure by adding a line to its definition:
@example
-hash_elem h_elem; /* Hash table element. */
+struct hash_elem h_elem; /* Hash table element. */
@end example
We'll choose the @code{tid} member in @struct{thread} as the key,
@example
/* Returns a hash for E. */
unsigned
-thread_hash (const hash_elem *e, void *aux UNUSED)
+thread_hash (const struct hash_elem *e, void *aux UNUSED)
@{
struct thread *t = hash_entry (e, struct thread, h_elem);
return hash_int (t->tid);
/* Returns true if A's tid is less than B's tid. */
bool
-thread_less (const hash_elem *a_, const hash_elem *b_,
+thread_less (const struct hash_elem *a_, const struct hash_elem *b_,
void *aux UNUSED)
@{
struct thread *a = hash_entry (a_, struct thread, h_elem);
}
/* Calibrates loops_per_tick, used to implement brief delays. */
-@@ -91,15 +96,35 @@ timer_elapsed (int64_t then)
+@@ -91,15 +96,36 @@ timer_elapsed (int64_t then)
return timer_ticks () - then;
}
+/* Compares two threads based on their wake-up times. */
+static bool
-+compare_threads_by_wakeup_time (const list_elem *a_, const list_elem *b_,
++compare_threads_by_wakeup_time (const struct list_elem *a_,
++ const struct list_elem *b_,
+ void *aux UNUSED)
+{
+ const struct thread *a = list_entry (a_, struct thread, timer_elem);
@@ -91,6 +92,11 @@ struct thread
/* Shared between thread.c and synch.c. */
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
+
+ /* Problem 1-1. */
+ int64_t wakeup_time; /* Time to wake this thread up. */
-+ list_elem timer_elem; /* Element in timer_wait_list. */
++ struct list_elem timer_elem; /* Element in timer_wait_list. */
+ struct semaphore timer_sema; /* Semaphore. */
#ifdef USERPROG
thread_exit (void)
{
+ struct thread *t = thread_current ();
-+ list_elem *e, *next;
++ struct list_elem *e, *next;
+
ASSERT (!intr_context ());
+thread_join (tid_t child_tid)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e;
++ struct list_elem *e;
+
+ for (e = list_begin (&cur->children); e != list_end (&cur->children); )
+ {
+ struct latch ready_to_die; /* Release when thread about to die. */
+ struct semaphore can_die; /* Up when thread allowed to die. */
+ struct list children; /* List of child threads. */
-+ list_elem children_elem; /* Element of `children' list. */
++ struct list_elem children_elem; /* Element of `children' list. */
+
/* Shared between thread.c and synch.c. */
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
diff -u -p -u -r1.15 synch.c
--- src/threads/synch.c 31 Dec 2004 21:13:38 -0000 1.15
+++ src/threads/synch.c 31 Dec 2004 22:31:03 -0000
-@@ -77,6 +77,17 @@ sema_down (struct semaphore *sema)
+@@ -77,6 +77,18 @@ sema_down (struct semaphore *sema)
intr_set_level (old_level);
}
+/* Returns true if thread A has lower priority than thread B. */
+static bool
-+donated_lower_priority (const list_elem *a_, const list_elem *b_,
++donated_lower_priority (const struct list_elem *a_,
++ const struct list_elem *b_,
+ void *aux UNUSED)
+{
+ const struct thread *a = list_entry (a_, struct thread, donor_elem);
{
enum intr_level old_level;
+ struct thread *t = thread_current ();
-+ list_elem *e;
++ struct list_elem *e;
ASSERT (lock != NULL);
ASSERT (lock_held_by_current_thread (lock));
return tid;
}
-@@ -186,6 +188,18 @@ thread_block (void)
+@@ -186,6 +188,19 @@ thread_block (void)
schedule ();
}
+/* Returns true if A has higher priority than B,
+ within a list of threads. */
+static bool
-+thread_higher_priority (const list_elem *a_, const list_elem *b_,
++thread_higher_priority (const struct list_elem *a_,
++ const struct list_elem *b_,
+ void *aux UNUSED)
+{
+ const struct thread *a = list_entry (a_, struct thread, elem);
schedule ();
intr_set_level (old_level);
}
-@@ -274,19 +288,74 @@
+@@ -274,19 +288,75 @@
{
}
+/* Returns true if thread A has lower priority than thread B,
+ within a list of donors. */
+static bool
-+donated_lower_priority (const list_elem *a_, const list_elem *b_,
-+ void *aux UNUSED)
++donated_lower_priority (const struct list_elem *a_,
++ const struct list_elem *b_,
++ void *aux UNUSED)
+{
+ const struct thread *a = list_entry (a_, struct thread, donor_elem);
+ const struct thread *b = list_entry (b_, struct thread, donor_elem);
+ int priority; /* Priority, including donations. */
+ int normal_priority; /* Priority, without donations. */
+ struct list donors; /* Threads donating priority to us. */
-+ list_elem donor_elem; /* Element in donors list. */
++ struct list_elem donor_elem; /* Element in donors list. */
+ struct thread *donee; /* Thread we're donating to. */
+ struct lock *want_lock; /* Lock we're waiting to acquire. */
/* Shared between thread.c and synch.c. */
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
@@ -118,6 +125,8 @@ const char *thread_name (void);
void thread_exit (void) NO_RETURN;
thread_exit (void)
{
+ struct thread *t = thread_current ();
-+ list_elem *e, *next;
++ struct list_elem *e, *next;
+
ASSERT (!intr_context ());
+thread_join (tid_t child_tid)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e;
++ struct list_elem *e;
+
+ for (e = list_begin (&cur->children); e != list_end (&cur->children); )
+ {
+ struct latch ready_to_die; /* Release when thread about to die. */
+ struct semaphore can_die; /* Up when thread allowed to die. */
+ struct list children; /* List of child threads. */
-+ list_elem children_elem; /* Element of `children' list. */
++ struct list_elem children_elem; /* Element of `children' list. */
+ int exit_code; /* Return status. */
+
/* Shared between thread.c and synch.c. */
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
#ifdef USERPROG
/* Owned by userprog/process.c. */
+/* A file descriptor, for binding a file handle to a file. */
+struct file_descriptor
+ {
-+ list_elem elem; /* List element. */
-+ struct file *file; /* File. */
-+ int handle; /* File handle. */
++ struct list_elem elem; /* List element. */
++ struct file *file; /* File. */
++ int handle; /* File handle. */
+ };
+
+/* Open system call. */
+lookup_fd (int handle)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e;
++ struct list_elem *e;
+
+ for (e = list_begin (&cur->fds); e != list_end (&cur->fds);
+ e = list_next (e))
+syscall_exit (void)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e, *next;
++ struct list_elem *e, *next;
+
+ for (e = list_begin (&cur->fds); e != list_end (&cur->fds); e = next)
+ {
thread_exit (void)
{
+ struct thread *t = thread_current ();
-+ list_elem *e, *next;
++ struct list_elem *e, *next;
+
ASSERT (!intr_context ());
+thread_join (tid_t child_tid)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e;
++ struct list_elem *e;
+
+ for (e = list_begin (&cur->children); e != list_end (&cur->children); )
+ {
+ struct latch ready_to_die; /* Release when thread about to die. */
+ struct semaphore can_die; /* Up when thread allowed to die. */
+ struct list children; /* List of child threads. */
-+ list_elem children_elem; /* Element of `children' list. */
++ struct list_elem children_elem; /* Element of `children' list. */
+ int ret_code; /* Return status. */
+
/* Shared between thread.c and synch.c. */
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
#ifdef USERPROG
/* Owned by userprog/process.c. */
bool user; /* True: access by user, false: access by kernel. */
void *fault_addr; /* Fault address. */
+ struct user_page tmp_up, *up;
-+ hash_elem *e;
++ struct hash_elem *e;
/* Obtain faulting address, the virtual address that was
accessed to cause the fault. It may point to code or to
}
}
-@@ -182,7 +189,10 @@ struct Elf32_Phdr
+@@ -182,7 +189,11 @@ struct Elf32_Phdr
#define PF_R 4 /* Readable. */
static bool load_segment (struct file *, const struct Elf32_Phdr *);
-static bool setup_stack (void **esp);
+static bool setup_stack (const char *cmdline, void **esp);
-+static unsigned user_page_hash (const hash_elem *, void *);
-+static bool user_page_less (const hash_elem *, const hash_elem *, void *);
++static unsigned user_page_hash (const struct hash_elem *, void *);
++static bool user_page_less (const struct hash_elem *, const struct hash_elem *,
++ void *);
+static struct user_page *make_user_page (void *upage);
/* Aborts loading an executable, with an error message. */
/* Is this a read-only segment? Not currently used, so it's
commented out. You'll want to use it when implementing VM
-@@ -340,70 +380,206 @@ load_segment (struct file *file, const s
+@@ -340,70 +380,207 @@ load_segment (struct file *file, const s
/* Load the segment page-by-page into memory. */
filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
+}
+
+static unsigned
-+user_page_hash (const hash_elem *e, void *aux UNUSED)
++user_page_hash (const struct hash_elem *e, void *aux UNUSED)
+{
+ struct user_page *up = hash_entry (e, struct user_page, elem);
+ return hash_bytes (&up->upage, sizeof up->upage);
- kpage = palloc_get_page (PAL_USER | PAL_ZERO);
- if (kpage != NULL)
+static bool
-+user_page_less (const hash_elem *a_, const hash_elem *b_, void *aux UNUSED)
++user_page_less (const struct hash_elem *a_,
++ const struct hash_elem *b_, void *aux UNUSED)
+{
+ struct user_page *a = hash_entry (a_, struct user_page, elem);
+ struct user_page *b = hash_entry (b_, struct user_page, elem);
+
+struct user_page
+ {
-+ hash_elem elem;
++ struct hash_elem elem;
+ void *upage; /* Virtual address of mapping. */
+
+ /* If FRAME is nonnull, the page is in memory.
+
+struct fildes
+ {
-+ list_elem elem;
++ struct list_elem elem;
+ struct file *file;
+ int handle;
+ };
+lookup_fd (int handle)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e;
++ struct list_elem *e;
+
+ for (e = list_begin (&cur->fds); e != list_end (&cur->fds);
+ e = list_next (e))
+syscall_exit (void)
+{
+ struct thread *cur = thread_current ();
-+ list_elem *e, *next;
++ struct list_elem *e, *next;
+
+ for (e = list_begin (&cur->fds); e != list_end (&cur->fds); e = next)
+ {
/* In-memory inode. */
struct inode
{
- list_elem elem; /* Element in inode list. */
+ struct list_elem elem; /* Element in inode list. */
disk_sector_t sector; /* Sector number of disk location. */
int open_cnt; /* Number of openers. */
bool removed; /* True if deleted, false otherwise. */
struct inode *
inode_open (disk_sector_t sector)
{
- list_elem *e;
+ struct list_elem *e;
struct inode *idx;
/* Check whether this inode is already open.
#include "../debug.h"
#include "threads/malloc.h"
-static struct list *find_bucket (struct hash *, hash_elem *);
-static struct list_elem *find_elem (struct hash *, struct list *, hash_elem *);
-static void insert_elem (struct hash *, struct list *, hash_elem *);
-static void remove_elem (struct hash *, hash_elem *);
+#define list_elem_to_hash_elem(LIST_ELEM) \
+ list_entry(LIST_ELEM, struct hash_elem, list_elem)
+
+static struct list *find_bucket (struct hash *, struct hash_elem *);
+static struct hash_elem *find_elem (struct hash *, struct list *,
+ struct hash_elem *);
+static void insert_elem (struct hash *, struct list *, struct hash_elem *);
+static void remove_elem (struct hash *, struct hash_elem *);
static void rehash (struct hash *);
/* Initializes hash table H to compute hash values using HASH and
no equal element is already in the table.
If an equal element is already in the table, returns it
without inserting NEW. */
-hash_elem *
-hash_insert (struct hash *h, hash_elem *new)
+struct hash_elem *
+hash_insert (struct hash *h, struct hash_elem *new)
{
struct list *bucket = find_bucket (h, new);
- struct list_elem *old = find_elem (h, bucket, new);
+ struct hash_elem *old = find_elem (h, bucket, new);
if (old == NULL)
insert_elem (h, bucket, new);
/* Inserts NEW into hash table H, replacing any equal element
already in the table, which is returned. */
-hash_elem *
-hash_replace (struct hash *h, hash_elem *new)
+struct hash_elem *
+hash_replace (struct hash *h, struct hash_elem *new)
{
struct list *bucket = find_bucket (h, new);
- struct list_elem *old = find_elem (h, bucket, new);
+ struct hash_elem *old = find_elem (h, bucket, new);
if (old != NULL)
remove_elem (h, old);
/* Finds and returns an element equal to E in hash table H, or a
null pointer if no equal element exists in the table. */
-hash_elem *
-hash_find (struct hash *h, hash_elem *e)
+struct hash_elem *
+hash_find (struct hash *h, struct hash_elem *e)
{
return find_elem (h, find_bucket (h, e), e);
}
/* Finds, removes, and returns an element equal to E in hash
table H. Returns a null pointer if no equal element existed
in the table. */
-hash_elem *
-hash_delete (struct hash *h, hash_elem *e)
+struct hash_elem *
+hash_delete (struct hash *h, struct hash_elem *e)
{
- struct list_elem *found = find_elem (h, find_bucket (h, e), e);
+ struct hash_elem *found = find_elem (h, find_bucket (h, e), e);
if (found != NULL)
{
remove_elem (h, found);
i->hash = h;
i->bucket = i->hash->buckets;
- i->elem = list_head (i->bucket);
+ i->elem = list_elem_to_hash_elem (list_head (i->bucket));
}
/* Advances I to the next element in the hash table and returns
NOTE: Modifying a hash table during iteration invalidates all
iterators. */
-hash_elem *
+struct hash_elem *
hash_next (struct hash_iterator *i)
{
ASSERT (i != NULL);
- i->elem = list_next (i->elem);
- while (i->elem == list_end (i->bucket))
+ i->elem = list_elem_to_hash_elem (list_next (&i->elem->list_elem));
+ while (i->elem == list_elem_to_hash_elem (list_end (i->bucket)))
{
if (++i->bucket >= i->hash->buckets + i->hash->bucket_cnt)
{
i->elem = NULL;
break;
}
- i->elem = list_begin (i->bucket);
+ i->elem = list_elem_to_hash_elem (list_begin (i->bucket));
}
return i->elem;
/* Returns the current element in the hash table iteration, or a
null pointer at the end of the table. Undefined behavior
after calling hash_first() but before hash_next(). */
-hash_elem *
+struct hash_elem *
hash_cur (struct hash_iterator *i)
{
return i->elem;
\f
/* Returns the bucket in H that E belongs in. */
static struct list *
-find_bucket (struct hash *h, hash_elem *e)
+find_bucket (struct hash *h, struct hash_elem *e)
{
size_t bucket_idx = h->hash (e, h->aux) & (h->bucket_cnt - 1);
return &h->buckets[bucket_idx];
/* Searches BUCKET in H for a hash element equal to E. Returns
it if found or a null pointer otherwise. */
-static struct list_elem *
-find_elem (struct hash *h, struct list *bucket, hash_elem *e)
+static struct hash_elem *
+find_elem (struct hash *h, struct list *bucket, struct hash_elem *e)
{
struct list_elem *i;
for (i = list_begin (bucket); i != list_end (bucket); i = list_next (i))
- if (!h->less (i, e, h->aux) && !h->less (e, i, h->aux))
- return i;
+ {
+ struct hash_elem *hi = list_elem_to_hash_elem (i);
+ if (!h->less (hi, e, h->aux) && !h->less (e, hi, h->aux))
+ return hi;
+ }
return NULL;
}
for (elem = list_begin (old_bucket);
elem != list_end (old_bucket); elem = next)
{
- struct list *new_bucket = find_bucket (h, elem);
+ struct list *new_bucket
+ = find_bucket (h, list_elem_to_hash_elem (elem));
next = list_next (elem);
list_remove (elem);
list_push_front (new_bucket, elem);
/* Inserts E into BUCKET (in hash table H). */
static void
-insert_elem (struct hash *h, struct list *bucket, hash_elem *e)
+insert_elem (struct hash *h, struct list *bucket, struct hash_elem *e)
{
h->elem_cnt++;
- list_push_front (bucket, e);
+ list_push_front (bucket, &e->list_elem);
}
/* Removes E from hash table H. */
static void
-remove_elem (struct hash *h, hash_elem *e)
+remove_elem (struct hash *h, struct hash_elem *e)
{
h->elem_cnt--;
- list_remove (e);
+ list_remove (&e->list_elem);
}
The chain lists do not use dynamic allocation. Instead, each
structure that can potentially be in a hash must embed a
- hash_elem member. All of the hash functions operate on these
- `hash_elem's. The hash_entry macro allows conversion from a
- hash_elem back to a structure object that contains it. This
- is the same technique used in the linked list implementation.
- Refer to lib/kernel/list.h for a detailed explanation.
+ struct hash_elem member. All of the hash functions operate on
+ these `struct hash_elem's. The hash_entry macro allows
+ conversion from a struct hash_elem back to a structure object
+ that contains it. This is the same technique used in the
+ linked list implementation. Refer to lib/kernel/list.h for a
+ detailed explanation.
The FAQ for the VM project contains a detailed example of how
to use the hash table. */
#include "list.h"
/* Hash element. */
-typedef list_elem hash_elem;
+struct hash_elem
+ {
+ struct list_elem list_elem;
+ };
/* Converts pointer to hash element HASH_ELEM into a pointer to
the structure that HASH_ELEM is embedded inside. Supply the
/* Computes and returns the hash value for hash element E, given
auxiliary data AUX. */
-typedef unsigned hash_hash_func (const hash_elem *e, void *aux);
+typedef unsigned hash_hash_func (const struct hash_elem *e, void *aux);
/* Compares the value of two hash elements A and B, given
auxiliary data AUX. Returns true if A is less than B, or
false if A is greater than or equal to B. */
-typedef bool hash_less_func (const hash_elem *a, const hash_elem *b,
+typedef bool hash_less_func (const struct hash_elem *a,
+ const struct hash_elem *b,
void *aux);
/* Hash table. */
{
struct hash *hash; /* The hash table. */
struct list *bucket; /* Current bucket. */
- hash_elem *elem; /* Current hash element in current bucket. */
+ struct hash_elem *elem; /* Current hash element in current bucket. */
};
/* Basic life cycle. */
void hash_destroy (struct hash *);
/* Search, insertion, deletion. */
-hash_elem *hash_insert (struct hash *, hash_elem *);
-hash_elem *hash_replace (struct hash *, hash_elem *);
-hash_elem *hash_find (struct hash *, hash_elem *);
-hash_elem *hash_delete (struct hash *, hash_elem *);
+struct hash_elem *hash_insert (struct hash *, struct hash_elem *);
+struct hash_elem *hash_replace (struct hash *, struct hash_elem *);
+struct hash_elem *hash_find (struct hash *, struct hash_elem *);
+struct hash_elem *hash_delete (struct hash *, struct hash_elem *);
/* Iteration. */
void hash_first (struct hash_iterator *, struct hash *);
-hash_elem *hash_next (struct hash_iterator *);
-hash_elem *hash_cur (struct hash_iterator *);
+struct hash_elem *hash_next (struct hash_iterator *);
+struct hash_elem *hash_cur (struct hash_iterator *);
/* Information. */
size_t hash_size (struct hash *);
/* Returns true if ELEM is a head, false otherwise. */
static inline bool
-is_head (list_elem *elem)
+is_head (struct list_elem *elem)
{
return elem != NULL && elem->prev == NULL && elem->next != NULL;
}
/* Returns true if ELEM is an interior element,
false otherwise. */
static inline bool
-is_interior (list_elem *elem)
+is_interior (struct list_elem *elem)
{
return elem != NULL && elem->prev != NULL && elem->next != NULL;
}
/* Returns true if ELEM is a tail, false otherwise. */
static inline bool
-is_tail (list_elem *elem)
+is_tail (struct list_elem *elem)
{
return elem != NULL && elem->prev != NULL && elem->next == NULL;
}
}
/* Returns the beginning of LIST. */
-list_elem *
+struct list_elem *
list_begin (struct list *list)
{
ASSERT (list != NULL);
/* Returns the element after ELEM in its list. If ELEM is the
last element in its list, returns the list tail. Results are
undefined if ELEM is itself a list tail. */
-list_elem *
-list_next (list_elem *elem)
+struct list_elem *
+list_next (struct list_elem *elem)
{
ASSERT (is_head (elem) || is_interior (elem));
return elem->next;
list_end() is often used in iterating through a list from
front to back. See the big comment at the top of list.h for
an example. */
-list_elem *
+struct list_elem *
list_end (struct list *list)
{
ASSERT (list != NULL);
/* Returns the LIST's reverse beginning, for iterating through
LIST in reverse order, from back to front. */
-list_elem *
+struct list_elem *
list_rbegin (struct list *list)
{
ASSERT (list != NULL);
/* Returns the element before ELEM in its list. If ELEM is the
first element in its list, returns the list head. Results are
undefined if ELEM is itself a list head. */
-list_elem *
-list_prev (list_elem *elem)
+struct list_elem *
+list_prev (struct list_elem *elem)
{
ASSERT (is_interior (elem) || is_tail (elem));
return elem->prev;
...do something with f...
}
*/
-list_elem *
+struct list_elem *
list_rend (struct list *list)
{
ASSERT (list != NULL);
...
}
*/
-list_elem *
+struct list_elem *
list_head (struct list *list)
{
ASSERT (list != NULL);
}
/* Return's LIST's tail. */
-list_elem *
+struct list_elem *
list_tail (struct list *list)
{
ASSERT (list != NULL);
interior element or a tail. The latter case is equivalent to
list_push_back(). */
void
-list_insert (list_elem *before, list_elem *elem)
+list_insert (struct list_elem *before, struct list_elem *elem)
{
ASSERT (is_interior (before) || is_tail (before));
ASSERT (elem != NULL);
current list, then inserts them just before BEFORE, which may
be either an interior element or a tail. */
void
-list_splice (list_elem *before,
- list_elem *first, list_elem *last)
+list_splice (struct list_elem *before,
+ struct list_elem *first, struct list_elem *last)
{
ASSERT (is_interior (before) || is_tail (before));
if (first == last)
/* Inserts ELEM at the beginning of LIST, so that it becomes the
front in LIST. */
void
-list_push_front (struct list *list, list_elem *elem)
+list_push_front (struct list *list, struct list_elem *elem)
{
list_insert (list_begin (list), elem);
}
/* Inserts ELEM at the end of LIST, so that it becomes the
back in LIST. */
void
-list_push_back (struct list *list, list_elem *elem)
+list_push_back (struct list *list, struct list_elem *elem)
{
list_insert (list_end (list), elem);
}
/* Removes ELEM from its list and returns the element that
followed it. Undefined behavior if ELEM is not in a list. */
-list_elem *
-list_remove (list_elem *elem)
+struct list_elem *
+list_remove (struct list_elem *elem)
{
ASSERT (is_interior (elem));
elem->prev->next = elem->next;
/* Removes the front element from LIST and returns it.
Undefined behavior if LIST is empty before removal. */
-list_elem *
+struct list_elem *
list_pop_front (struct list *list)
{
- list_elem *front = list_front (list);
+ struct list_elem *front = list_front (list);
list_remove (front);
return front;
}
/* Removes the back element from LIST and returns it.
Undefined behavior if LIST is empty before removal. */
-list_elem *
+struct list_elem *
list_pop_back (struct list *list)
{
- list_elem *back = list_back (list);
+ struct list_elem *back = list_back (list);
list_remove (back);
return back;
}
/* Returns the front element in LIST.
Undefined behavior if LIST is empty. */
-list_elem *
+struct list_elem *
list_front (struct list *list)
{
ASSERT (!list_empty (list));
/* Returns the back element in LIST.
Undefined behavior if LIST is empty. */
-list_elem *
+struct list_elem *
list_back (struct list *list)
{
ASSERT (!list_empty (list));
size_t
list_size (struct list *list)
{
- list_elem *e;
+ struct list_elem *e;
size_t cnt = 0;
for (e = list_begin (list); e != list_end (list); e = list_next (e))
return list_begin (list) == list_end (list);
}
-/* Swaps the `list_elem *'s that A and B point to. */
+/* Swaps the `struct list_elem *'s that A and B point to. */
static void
-swap (list_elem **a, list_elem **b)
+swap (struct list_elem **a, struct list_elem **b)
{
- list_elem *t = *a;
+ struct list_elem *t = *a;
*a = *b;
*b = t;
}
{
if (!list_empty (list))
{
- list_elem *e;
+ struct list_elem *e;
for (e = list_begin (list); e != list_end (list); e = e->prev)
swap (&e->prev, &e->next);
list_merge (struct list *al, struct list *bl,
list_less_func *less, void *aux)
{
- list_elem *a;
+ struct list_elem *a;
ASSERT (al != NULL);
ASSERT (bl != NULL);
a = list_begin (al);
while (a != list_end (al))
{
- list_elem *b = list_begin (bl);
+ struct list_elem *b = list_begin (bl);
if (less (b, a, aux))
{
list_splice (a, b, list_next (b));
/* Returns the middle element in LIST, that is, the N/2'th
element (rounding down) in a N-element list.
Given an empty list, returns the list tail. */
-static list_elem *
+static struct list_elem *
middle_of_list (struct list *list)
{
- list_elem *middle, *last;
+ struct list_elem *middle, *last;
middle = last = list_begin (list);
while (last != list_end (list) && list_next (last) != list_end (list))
list_less_func *less, void *aux)
{
/* Find the middle of the list. */
- list_elem *middle = middle_of_list (list);
+ struct list_elem *middle = middle_of_list (list);
if (middle != list_begin (list))
{
/* Extract first half of LIST into a temporary list. */
sorted according to LESS given auxiliary data AUX.
Runs in O(n) average case in the number of elements in LIST. */
void
-list_insert_ordered (struct list *list, list_elem *elem,
+list_insert_ordered (struct list *list, struct list_elem *elem,
list_less_func *less, void *aux)
{
- list_elem *e;
+ struct list_elem *e;
ASSERT (list != NULL);
ASSERT (elem != NULL);
list_unique (struct list *list, struct list *duplicates,
list_less_func *less, void *aux)
{
- list_elem *elem, *next;
+ struct list_elem *elem, *next;
ASSERT (list != NULL);
ASSERT (less != NULL);
to LESS given auxiliary data AUX. If there is more than one
maximum, returns the one that appears earlier in the list. If
the list is empty, returns its tail. */
-list_elem *
+struct list_elem *
list_max (struct list *list, list_less_func *less, void *aux)
{
- list_elem *max = list_begin (list);
+ struct list_elem *max = list_begin (list);
if (max != list_end (list))
{
- list_elem *e;
+ struct list_elem *e;
for (e = list_next (max); e != list_end (list); e = list_next (e))
if (less (max, e, aux))
to LESS given auxiliary data AUX. If there is more than one
minimum, returns the one that appears earlier in the list. If
the list is empty, returns its tail. */
-list_elem *
+struct list_elem *
list_min (struct list *list, list_less_func *less, void *aux)
{
- list_elem *min = list_begin (list);
+ struct list_elem *min = list_begin (list);
if (min != list_end (list))
{
- list_elem *e;
+ struct list_elem *e;
for (e = list_next (min); e != list_end (list); e = list_next (e))
if (less (e, min, aux))
This implementation of a doubly linked list does not require
use of dynamically allocated memory. Instead, each structure
- that is a potential list element must embed a list_elem
- member. All of the list functions operate on these
- `list_elem's. The list_entry macro allows conversion from a
- list_elem back to a structure object that contains it.
+ that is a potential list element must embed a struct list_elem
+ member. All of the list functions operate on these `struct
+ list_elem's. The list_entry macro allows conversion from a
+ struct list_elem back to a structure object that contains it.
For example, suppose there is a needed for a list of `struct
- foo'. `struct foo' should contain a `list_elem' member, like
- so:
+ foo'. `struct foo' should contain a `struct list_elem'
+ member, like so:
struct foo
{
- list_elem elem;
+ struct list_elem elem;
int bar;
...other members...
};
list_init (&foo_list);
Iteration is a typical situation where it is necessary to
- convert from a list_elem back to its enclosing structure.
- Here's an example using foo_list:
+ convert from a struct list_elem back to its enclosing
+ structure. Here's an example using foo_list:
- list_elem *e;
+ struct list_elem *e;
for (e = list_begin (&foo_list); e != list_end (&foo_list);
e = list_next (e))
#include <stdint.h>
/* List element. */
-typedef struct list_elem
+struct list_elem
{
struct list_elem *prev; /* Previous list element. */
struct list_elem *next; /* Next list element. */
- }
-list_elem;
+ };
/* List. */
struct list
{
- list_elem head; /* List head. */
- list_elem tail; /* List tail. */
+ struct list_elem head; /* List head. */
+ struct list_elem tail; /* List tail. */
};
/* Converts pointer to list element LIST_ELEM into a pointer to
void list_init (struct list *);
/* List traversal. */
-list_elem *list_begin (struct list *);
-list_elem *list_next (list_elem *);
-list_elem *list_end (struct list *);
+struct list_elem *list_begin (struct list *);
+struct list_elem *list_next (struct list_elem *);
+struct list_elem *list_end (struct list *);
-list_elem *list_rbegin (struct list *);
-list_elem *list_prev (list_elem *);
-list_elem *list_rend (struct list *);
+struct list_elem *list_rbegin (struct list *);
+struct list_elem *list_prev (struct list_elem *);
+struct list_elem *list_rend (struct list *);
-list_elem *list_head (struct list *);
-list_elem *list_tail (struct list *);
+struct list_elem *list_head (struct list *);
+struct list_elem *list_tail (struct list *);
/* List insertion. */
-void list_insert (list_elem *, list_elem *);
-void list_splice (list_elem *before,
- list_elem *first, list_elem *last);
-void list_push_front (struct list *, list_elem *);
-void list_push_back (struct list *, list_elem *);
+void list_insert (struct list_elem *, struct list_elem *);
+void list_splice (struct list_elem *before,
+ struct list_elem *first, struct list_elem *last);
+void list_push_front (struct list *, struct list_elem *);
+void list_push_back (struct list *, struct list_elem *);
/* List removal. */
-list_elem *list_remove (list_elem *);
-list_elem *list_pop_front (struct list *);
-list_elem *list_pop_back (struct list *);
+struct list_elem *list_remove (struct list_elem *);
+struct list_elem *list_pop_front (struct list *);
+struct list_elem *list_pop_back (struct list *);
/* List elements. */
-list_elem *list_front (struct list *);
-list_elem *list_back (struct list *);
+struct list_elem *list_front (struct list *);
+struct list_elem *list_back (struct list *);
/* List properties. */
size_t list_size (struct list *);
/* Compares the value of two list elements A and B, given
auxiliary data AUX. Returns true if A is less than B, or
false if A is greater than or equal to B. */
-typedef bool list_less_func (const list_elem *a, const list_elem *b,
+typedef bool list_less_func (const struct list_elem *a,
+ const struct list_elem *b,
void *aux);
/* Operations on lists with ordered elements. */
list_less_func *, void *aux);
void list_sort (struct list *,
list_less_func *, void *aux);
-void list_insert_ordered (struct list *, list_elem *,
+void list_insert_ordered (struct list *, struct list_elem *,
list_less_func *, void *aux);
void list_unique (struct list *, struct list *duplicates,
list_less_func *, void *aux);
/* Max and min. */
-list_elem *list_max (struct list *, list_less_func *, void *aux);
-list_elem *list_min (struct list *, list_less_func *, void *aux);
+struct list_elem *list_max (struct list *, list_less_func *, void *aux);
+struct list_elem *list_min (struct list *, list_less_func *, void *aux);
#endif /* lib/kernel/list.h */
/* A linked list element. */
struct value
{
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
int value; /* Item value. */
};
static void shuffle (struct value[], size_t);
-static bool value_less (const list_elem *, const list_elem *, void *);
+static bool value_less (const struct list_elem *, const struct list_elem *,
+ void *);
static void verify_list_fwd (struct list *, int size);
static void verify_list_bkwd (struct list *, int size);
{
static struct value values[MAX_SIZE * 4];
struct list list;
- list_elem *e;
+ struct list_elem *e;
int i, ofs;
/* Put values 0...SIZE in random order in VALUES. */
/* Returns true if value A is less than value B, false
otherwise. */
static bool
-value_less (const list_elem *a_, const list_elem *b_, void *aux UNUSED)
+value_less (const struct list_elem *a_, const struct list_elem *b_,
+ void *aux UNUSED)
{
const struct value *a = list_entry (a_, struct value, elem);
const struct value *b = list_entry (b_, struct value, elem);
static void
verify_list_fwd (struct list *list, int size)
{
- list_elem *e;
+ struct list_elem *e;
int i;
for (i = 0, e = list_begin (list);
static void
verify_list_bkwd (struct list *list, int size)
{
- list_elem *e;
+ struct list_elem *e;
int i;
for (i = 0, e = list_rbegin (list);
/* Free block. */
struct block
{
- list_elem free_elem; /* Free list element. */
+ struct list_elem free_elem; /* Free list element. */
};
/* Our set of descriptors. */
/* One semaphore in a list. */
struct semaphore_elem
{
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
struct semaphore semaphore; /* This semaphore. */
};
int priority; /* Priority. */
/* Shared between thread.c and synch.c. */
- list_elem elem; /* List element. */
+ struct list_elem elem; /* List element. */
#ifdef USERPROG
/* Owned by userprog/process.c. */