aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog28
-rw-r--r--gold/common.cc11
-rw-r--r--gold/common.h8
-rw-r--r--gold/gold.cc63
-rw-r--r--gold/reloc.cc38
-rw-r--r--gold/reloc.h49
6 files changed, 123 insertions, 74 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 346806f..03191eb 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,33 @@
2010-02-11 Ian Lance Taylor <iant@google.com>
+ * gold.cc (queue_middle_gc_tasks): Use a separate blocker for each
+ Read_relocs task.
+ (queue_middle_tasks): Likewise, and also for Scan_relocs. Run
+ Allocate_commons_task first.
+ * reloc.cc (Read_relocs::run): Pass next_blocker_ down to next
+ task, rather than symtab_lock_.
+ (Gc_process_relocs::~Gc_process_relocs): New function.
+ (Gc_process_relocs::is_runnable): Check this_blocker_.
+ (Gc_process_relocs::locks): Use next_blocker_ rather than
+ blocker_.
+ (Scan_relocs::~Scan_relocs): New function.
+ (Scan_relocs::is_runnable): Check this_blocker_ rather than
+ symtab_lock_.
+ (Scan_relocs::locks): Drop symtab_lock_ and blocker_. Add
+ next_blocker_.
+ * reloc.h (class Read_relocs): Drop symtab_lock_ and blocker_
+ fields. Add this_blocker_ and next_blocker_ fields. Adjust
+ constructor accordingly.
+ (class Gc_process_relocs): Likewise.
+ (class Scan_relocs): Likewise.
+ * common.h (class Allocate_commons_task): Remove symtab_lock_
+ field, and corresponding constructor parameter.
+ * common.cc (Allocate_commons_tasK::is_runnable): Remove use of
+ symtab_lock_.
+ (Allocate_commons_task::locks): Likewise.
+
+2010-02-11 Ian Lance Taylor <iant@google.com>
+
* gold-threads.h (class Once): Define.
(class Initialize_lock): Rewrite as child of Once.
* gold-threads.cc (class Once_initialize): Define.
diff --git a/gold/common.cc b/gold/common.cc
index 8859338..8346c0b 100644
--- a/gold/common.cc
+++ b/gold/common.cc
@@ -1,6 +1,6 @@
// common.cc -- handle common symbols for gold
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -36,24 +36,21 @@ namespace gold
// Allocate_commons_task methods.
-// This task allocates the common symbols. We need a lock on the
-// symbol table.
+// This task allocates the common symbols. We arrange to run it
+// before anything else which needs to access the symbol table.
Task_token*
Allocate_commons_task::is_runnable()
{
- if (!this->symtab_lock_->is_writable())
- return this->symtab_lock_;
return NULL;
}
-// Return the locks we hold: one on the symbol table, and one blocker.
+// Release a blocker.
void
Allocate_commons_task::locks(Task_locker* tl)
{
tl->add(this, this->blocker_);
- tl->add(this, this->symtab_lock_);
}
// Allocate the common symbols.
diff --git a/gold/common.h b/gold/common.h
index 9653604..4de585c 100644
--- a/gold/common.h
+++ b/gold/common.h
@@ -1,6 +1,6 @@
// common.h -- handle common symbols for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -36,9 +36,8 @@ class Allocate_commons_task : public Task
{
public:
Allocate_commons_task(Symbol_table* symtab, Layout* layout, Mapfile* mapfile,
- Task_token* symtab_lock, Task_token* blocker)
- : symtab_(symtab), layout_(layout), mapfile_(mapfile),
- symtab_lock_(symtab_lock), blocker_(blocker)
+ Task_token* blocker)
+ : symtab_(symtab), layout_(layout), mapfile_(mapfile), blocker_(blocker)
{ }
// The standard Task methods.
@@ -60,7 +59,6 @@ class Allocate_commons_task : public Task
Symbol_table* symtab_;
Layout* layout_;
Mapfile* mapfile_;
- Task_token* symtab_lock_;
Task_token* blocker_;
};
diff --git a/gold/gold.cc b/gold/gold.cc
index c419432..275d0f9 100644
--- a/gold/gold.cc
+++ b/gold/gold.cc
@@ -265,21 +265,23 @@ queue_middle_gc_tasks(const General_options& options,
{
// Read_relocs for all the objects must be done and processed to find
// unused sections before any scanning of the relocs can take place.
- Task_token* blocker = new Task_token(true);
- blocker->add_blockers(input_objects->number_of_relobjs());
- Task_token* symtab_lock = new Task_token(false);
+ Task_token* this_blocker = NULL;
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
++p)
- workqueue->queue(new Read_relocs(symtab, layout, *p, symtab_lock,
- blocker));
-
+ {
+ Task_token* next_blocker = new Task_token(true);
+ next_blocker->add_blocker();
+ workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker,
+ next_blocker));
+ this_blocker = next_blocker;
+ }
workqueue->queue(new Task_function(new Middle_runner(options,
input_objects,
symtab,
layout,
mapfile),
- blocker,
+ this_blocker,
"Task_function Middle_runner"));
}
@@ -475,12 +477,18 @@ queue_middle_tasks(const General_options& options,
// Make sure we have symbols for any required group signatures.
layout->define_group_signatures(symtab);
- Task_token* blocker = new Task_token(true);
- blocker->add_blockers(input_objects->number_of_relobjs());
- if (parameters->options().define_common())
- blocker->add_blocker();
+ Task_token* this_blocker = NULL;
- Task_token* symtab_lock = new Task_token(false);
+ // Allocate common symbols. We use a blocker to run this before the
+ // Scan_relocs tasks, because it writes to the symbol table just as
+ // they do.
+ if (parameters->options().define_common())
+ {
+ this_blocker = new Task_token(true);
+ this_blocker->add_blocker();
+ workqueue->queue(new Allocate_commons_task(symtab, layout, mapfile,
+ this_blocker));
+ }
// If doing garbage collection, the relocations have already been read.
// Otherwise, read and scan the relocations.
@@ -490,9 +498,14 @@ queue_middle_tasks(const General_options& options,
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
++p)
- workqueue->queue(new Scan_relocs(symtab, layout, *p,
- (*p)->get_relocs_data(),
- symtab_lock, blocker));
+ {
+ Task_token* next_blocker = new Task_token(true);
+ next_blocker->add_blocker();
+ workqueue->queue(new Scan_relocs(symtab, layout, *p,
+ (*p)->get_relocs_data(),
+ this_blocker, next_blocker));
+ this_blocker = next_blocker;
+ }
}
else
{
@@ -511,22 +524,14 @@ queue_middle_tasks(const General_options& options,
p != input_objects->relobj_end();
++p)
{
- // We can read and process the relocations in any order. But we
- // only want one task to write to the symbol table at a time.
- // So we queue up a task for each object to read the
- // relocations. That task will in turn queue a task to wait
- // until it can write to the symbol table.
- workqueue->queue(new Read_relocs(symtab, layout, *p, symtab_lock,
- blocker));
+ Task_token* next_blocker = new Task_token(true);
+ next_blocker->add_blocker();
+ workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker,
+ next_blocker));
+ this_blocker = next_blocker;
}
}
- // Allocate common symbols. This requires write access to the
- // symbol table, but is independent of the relocation processing.
- if (parameters->options().define_common())
- workqueue->queue(new Allocate_commons_task(symtab, layout, mapfile,
- symtab_lock, blocker));
-
// When all those tasks are complete, we can start laying out the
// output file.
// TODO(csilvers): figure out a more principled way to get the target
@@ -537,7 +542,7 @@ queue_middle_tasks(const General_options& options,
target,
layout,
mapfile),
- blocker,
+ this_blocker,
"Task_function Layout_task_runner"));
}
diff --git a/gold/reloc.cc b/gold/reloc.cc
index 858778e..0061059 100644
--- a/gold/reloc.cc
+++ b/gold/reloc.cc
@@ -1,6 +1,6 @@
// reloc.cc -- relocate input files for gold.
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -75,15 +75,15 @@ Read_relocs::run(Workqueue* workqueue)
workqueue->queue_next(new Gc_process_relocs(this->symtab_,
this->layout_,
this->object_, rd,
- this->symtab_lock_,
- this->blocker_));
+ this->this_blocker_,
+ this->next_blocker_));
}
else
{
workqueue->queue_next(new Scan_relocs(this->symtab_, this->layout_,
this->object_, rd,
- this->symtab_lock_,
- this->blocker_));
+ this->this_blocker_,
+ this->next_blocker_));
}
}
@@ -97,13 +97,22 @@ Read_relocs::get_name() const
// Gc_process_relocs methods.
-// These tasks process the relocations read by Read_relocs and
+Gc_process_relocs::~Gc_process_relocs()
+{
+ if (this->this_blocker_ != NULL)
+ delete this->this_blocker_;
+}
+
+// These tasks process the relocations read by Read_relocs and
// determine which sections are referenced and which are garbage.
-// This task is done only when --gc-sections is used.
+// This task is done only when --gc-sections is used. This is blocked
+// by THIS_BLOCKER_. It unblocks NEXT_BLOCKER_.
Task_token*
Gc_process_relocs::is_runnable()
{
+ if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
+ return this->this_blocker_;
if (this->object_->is_locked())
return this->object_->token();
return NULL;
@@ -113,7 +122,7 @@ void
Gc_process_relocs::locks(Task_locker* tl)
{
tl->add(this, this->object_->token());
- tl->add(this, this->blocker_);
+ tl->add(this, this->next_blocker_);
}
void
@@ -133,6 +142,12 @@ Gc_process_relocs::get_name() const
// Scan_relocs methods.
+Scan_relocs::~Scan_relocs()
+{
+ if (this->this_blocker_ != NULL)
+ delete this->this_blocker_;
+}
+
// These tasks scan the relocations read by Read_relocs and mark up
// the symbol table to indicate which relocations are required. We
// use a lock on the symbol table to keep them from interfering with
@@ -141,8 +156,8 @@ Gc_process_relocs::get_name() const
Task_token*
Scan_relocs::is_runnable()
{
- if (!this->symtab_lock_->is_writable())
- return this->symtab_lock_;
+ if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
+ return this->this_blocker_;
if (this->object_->is_locked())
return this->object_->token();
return NULL;
@@ -155,8 +170,7 @@ void
Scan_relocs::locks(Task_locker* tl)
{
tl->add(this, this->object_->token());
- tl->add(this, this->symtab_lock_);
- tl->add(this, this->blocker_);
+ tl->add(this, this->next_blocker_);
}
// Scan the relocs.
diff --git a/gold/reloc.h b/gold/reloc.h
index 5dd4c85..f99da0c 100644
--- a/gold/reloc.h
+++ b/gold/reloc.h
@@ -1,6 +1,6 @@
// reloc.h -- relocate input files for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -62,12 +62,13 @@ class Output_data_reloc;
class Read_relocs : public Task
{
public:
- // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be
- // unblocked when the Scan_relocs task completes.
+ // THIS_BLOCKER and NEXT_BLOCKER are passed along to a Scan_relocs
+ // or Gc_process_relocs task, so that they run in a deterministic
+ // order.
Read_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
- Task_token* symtab_lock, Task_token* blocker)
+ Task_token* this_blocker, Task_token* next_blocker)
: symtab_(symtab), layout_(layout), object_(object),
- symtab_lock_(symtab_lock), blocker_(blocker)
+ this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
// The standard Task methods.
@@ -88,8 +89,8 @@ class Read_relocs : public Task
Symbol_table* symtab_;
Layout* layout_;
Relobj* object_;
- Task_token* symtab_lock_;
- Task_token* blocker_;
+ Task_token* this_blocker_;
+ Task_token* next_blocker_;
};
// Process the relocs to figure out which sections are garbage.
@@ -98,15 +99,18 @@ class Read_relocs : public Task
class Gc_process_relocs : public Task
{
public:
- // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be
- // unblocked when the task completes.
+ // THIS_BLOCKER prevents this task from running until the previous
+ // one is finished. NEXT_BLOCKER prevents the next task from
+ // running.
Gc_process_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
- Read_relocs_data* rd, Task_token* symtab_lock,
- Task_token* blocker)
+ Read_relocs_data* rd, Task_token* this_blocker,
+ Task_token* next_blocker)
: symtab_(symtab), layout_(layout), object_(object), rd_(rd),
- symtab_lock_(symtab_lock), blocker_(blocker)
+ this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
+ ~Gc_process_relocs();
+
// The standard Task methods.
Task_token*
@@ -126,8 +130,8 @@ class Gc_process_relocs : public Task
Layout* layout_;
Relobj* object_;
Read_relocs_data* rd_;
- Task_token* symtab_lock_;
- Task_token* blocker_;
+ Task_token* this_blocker_;
+ Task_token* next_blocker_;
};
// Scan the relocations for an object to see if they require any
@@ -136,15 +140,18 @@ class Gc_process_relocs : public Task
class Scan_relocs : public Task
{
public:
- // SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be
- // unblocked when the task completes.
+ // THIS_BLOCKER prevents this task from running until the previous
+ // one is finished. NEXT_BLOCKER prevents the next task from
+ // running.
Scan_relocs(Symbol_table* symtab, Layout* layout, Relobj* object,
- Read_relocs_data* rd, Task_token* symtab_lock,
- Task_token* blocker)
+ Read_relocs_data* rd, Task_token* this_blocker,
+ Task_token* next_blocker)
: symtab_(symtab), layout_(layout), object_(object), rd_(rd),
- symtab_lock_(symtab_lock), blocker_(blocker)
+ this_blocker_(this_blocker), next_blocker_(next_blocker)
{ }
+ ~Scan_relocs();
+
// The standard Task methods.
Task_token*
@@ -164,8 +171,8 @@ class Scan_relocs : public Task
Layout* layout_;
Relobj* object_;
Read_relocs_data* rd_;
- Task_token* symtab_lock_;
- Task_token* blocker_;
+ Task_token* this_blocker_;
+ Task_token* next_blocker_;
};
// A class to perform all the relocations for an object file.