X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=blobdiff_plain;f=src%2Fthreads%2Fthread.c;h=2532463bdbbf5d8f2544cba0b590ae070d2d07e1;hp=92d1aa899efe1d8bf84c6c7056ae7d45215c687b;hb=3edcfedb8e62970f3293fa676b6691f8658c3c11;hpb=ef87ec47544e7a120d19211b6332d41b11403992 diff --git a/src/threads/thread.c b/src/threads/thread.c index 92d1aa8..2532463 100644 --- a/src/threads/thread.c +++ b/src/threads/thread.c @@ -24,6 +24,10 @@ that are ready to run but not actually running. */ static struct list ready_list; +/* List of all processes. Processes are added to this list + when they are first scheduled and removed when they exit. */ +static struct list all_list; + /* Idle thread. */ static struct thread *idle_thread; @@ -87,6 +91,7 @@ thread_init (void) lock_init (&tid_lock); list_init (&ready_list); + list_init (&all_list); /* Set up a thread structure for the running thread. */ initial_thread = running_thread (); @@ -166,6 +171,7 @@ thread_create (const char *name, int priority, struct switch_entry_frame *ef; struct switch_threads_frame *sf; tid_t tid; + enum intr_level old_level; ASSERT (function != NULL); @@ -178,6 +184,11 @@ thread_create (const char *name, int priority, init_thread (t, name, priority); tid = t->tid = allocate_tid (); + /* Prepare thread for first run by initializing its stack. + Do this atomically so intermediate values for the 'stack' + member cannot be observed. */ + old_level = intr_disable (); + /* Stack frame for kernel_thread(). */ kf = alloc_frame (t, sizeof *kf); kf->eip = NULL; @@ -191,6 +202,9 @@ thread_create (const char *name, int priority, /* Stack frame for switch_threads(). */ sf = alloc_frame (t, sizeof *sf); sf->eip = switch_entry; + sf->ebp = 0; + + intr_set_level (old_level); /* Add to run queue. */ thread_unblock (t); @@ -280,9 +294,11 @@ thread_exit (void) process_exit (); #endif - /* Just set our status to dying and schedule another process. - We will be destroyed during the call to schedule_tail(). */ + /* Remove thread from all threads list, set our status to dying, + and schedule another process. That process will destroy us + when it call schedule_tail(). */ intr_disable (); + list_remove (&thread_current()->allelem); thread_current ()->status = THREAD_DYING; schedule (); NOT_REACHED (); @@ -306,6 +322,23 @@ thread_yield (void) intr_set_level (old_level); } +/* Invoke function 'func' on all threads, passing along 'aux'. + This function must be called with interrupts off. */ +void +thread_foreach (thread_action_func *func, void *aux) +{ + struct list_elem *e; + + ASSERT (intr_get_level () == INTR_OFF); + + for (e = list_begin (&all_list); e != list_end (&all_list); + e = list_next (e)) + { + struct thread *t = list_entry (e, struct thread, allelem); + func (t, aux); + } +} + /* Sets the current thread's priority to NEW_PRIORITY. */ void thread_set_priority (int new_priority) @@ -436,6 +469,7 @@ init_thread (struct thread *t, const char *name, int priority) t->stack = (uint8_t *) t + PGSIZE; t->priority = priority; t->magic = THREAD_MAGIC; + list_push_back (&all_list, &t->allelem); } /* Allocates a SIZE-byte frame at the top of thread T's stack and