Merge branch 'crio-compiling-switch' into network-robot-new
diff --git a/aos/atom_code/input/FRCComm.h b/aos/atom_code/input/FRCComm.h
index 14c4602..98619de 100644
--- a/aos/atom_code/input/FRCComm.h
+++ b/aos/atom_code/input/FRCComm.h
@@ -124,7 +124,6 @@
 	UINT32 FPGAChecksum3;
 
 	char versionData[8];
-};
-
+} __attribute__((packed));
 
 #endif
diff --git a/aos/build/aos.gypi b/aos/build/aos.gypi
index 662a419..115ae06 100644
--- a/aos/build/aos.gypi
+++ b/aos/build/aos.gypi
@@ -44,6 +44,8 @@
     'defines': [
       '__STDC_FORMAT_MACROS',
       '_FORTIFY_SOURCE=2',
+      '__STDC_CONSTANT_MACROS',
+      '__STDC_LIMIT_MACROS',
     ],
     'ldflags': [
       '-pipe',
diff --git a/aos/build/download_externals.sh b/aos/build/download_externals.sh
index 5e07d02..4f999b2 100755
--- a/aos/build/download_externals.sh
+++ b/aos/build/download_externals.sh
@@ -89,3 +89,10 @@
   CFLAGS='-m32' CXXFLAGS='-m32' LDFLAGS='-m32' \
   bash -c "cd ${LIBUSB_DIR} && ./configure \
   --prefix=`readlink -f ${LIBUSB_PREFIX}` && make && make install"
+
+# get the LLVM Compiler-RT source
+COMPILER_RT_TAG=RELEASE_32/final
+COMPILER_RT_VERSION=`echo ${COMPILER_RT_TAG} | sed s:/:_:`
+COMPILER_RT_DIR=${EXTERNALS}/compiler-rt-${COMPILER_RT_VERSION}
+COMPILER_RT_URL=http://llvm.org/svn/llvm-project/compiler-rt/tags/${COMPILER_RT_TAG}
+[ -d ${COMPILER_RT_DIR} ] || svn checkout ${COMPILER_RT_URL} ${COMPILER_RT_DIR}
diff --git a/aos/build/externals.gyp b/aos/build/externals.gyp
index 0fa5fed..0daa229 100644
--- a/aos/build/externals.gyp
+++ b/aos/build/externals.gyp
@@ -13,6 +13,7 @@
     'gflags_version': '2.0',
     'libusb_version': '1.0.9',
     'libusb_apiversion': '1.0',
+    'compiler_rt_version': 'RELEASE_32_final',
   },
   'targets': [
     {
@@ -187,4 +188,7 @@
       },
     },
   ],
+  'includes': [
+    'libgcc-additions/libgcc-additions.gypi',
+  ],
 }
diff --git a/aos/build/libgcc-additions/README b/aos/build/libgcc-additions/README
new file mode 100644
index 0000000..6a9a665
--- /dev/null
+++ b/aos/build/libgcc-additions/README
@@ -0,0 +1,26 @@
+This directory contains the stuff necessary to deal with the fact that the
+  libgcc.a from the old GCC that the cRIO has doesn't have all of the functions
+  that newer GCCs expect from it.
+
+[extra functions necessary for 4.5.2]
+I generated this diff with `powerpc-wrs-vxworks-nm \
+  gccdist/WindRiver/gnu/3.4.4-vxworks-6.3/x86-win32/lib/gcc/powerpc-wrs-vxworks/3.4.4/libgcc.a \
+  | fgrep '000 T' | awk ' { print $NF }'` (and using the same command with the
+  gccdist.a from the 4.5.2 GCC.
+  I then gave the outputs from both of those to diff and edited out by hand the
+  functions that just moved.
+__powisf2
+__powidf2
+__mulsc3
+__muldc3
+__divsc3
+__divdc3
+__bswapsi2
+__bswapdi2
+__floatundisf
+__floatundidf
+__eprintf
+
+eprintf looks like it's not needed.
+Compiler-RT thinks that bswapsi2 and bswapdi2 are only needed on arm, so it
+  only has arm assembly for them.
diff --git a/aos/build/libgcc-additions/_bswapdi2.o b/aos/build/libgcc-additions/_bswapdi2.o
new file mode 100644
index 0000000..8bc6f56
--- /dev/null
+++ b/aos/build/libgcc-additions/_bswapdi2.o
Binary files differ
diff --git a/aos/build/libgcc-additions/_bswapsi2.o b/aos/build/libgcc-additions/_bswapsi2.o
new file mode 100644
index 0000000..4700ad8
--- /dev/null
+++ b/aos/build/libgcc-additions/_bswapsi2.o
Binary files differ
diff --git a/aos/build/libgcc-additions/libgcc-additions.gypi b/aos/build/libgcc-additions/libgcc-additions.gypi
new file mode 100644
index 0000000..8090f7c
--- /dev/null
+++ b/aos/build/libgcc-additions/libgcc-additions.gypi
@@ -0,0 +1,33 @@
+{
+  'targets': [
+    {
+      'target_name': 'libgcc-4.5.2',
+      'type': 'static_library',
+      'variables': {
+        'compiler-rt': '<(externals)/compiler-rt-<(compiler_rt_version)',
+      },
+      'include_dirs': [
+        '<(compiler-rt)/lib',
+      ],
+      'defines': [
+        '_YUGA_BIG_ENDIAN=1',
+        '_YUGA_LITTLE_ENDIAN=0',
+        'UINT64_C(c)=c##ULL',
+      ],
+      'sources': [
+        '<(compiler-rt)/lib/powisf2.c',
+        '<(compiler-rt)/lib/powidf2.c',
+        '<(compiler-rt)/lib/mulsc3.c',
+        '<(compiler-rt)/lib/muldc3.c',
+        '<(compiler-rt)/lib/divsc3.c',
+        '<(compiler-rt)/lib/divdc3.c',
+        #'<(compiler-rt)/lib/bswapsi2.c',
+        '_bswapsi2.o',
+        #'<(compiler-rt)/lib/bswapdi2.c',
+        '_bswapdi2.o',
+        '<(compiler-rt)/lib/floatundisf.c',
+        '<(compiler-rt)/lib/floatundidf.c',
+      ],
+    },
+  ],
+}
diff --git a/aos/externals/.gitignore b/aos/externals/.gitignore
index 7f6c98d..64c3acf 100644
--- a/aos/externals/.gitignore
+++ b/aos/externals/.gitignore
@@ -21,3 +21,4 @@
 /libusb-1.0.9-prefix/
 /libusb-1.0.9.tar.bz2
 /libusb-1.0.9/
+/compiler-rt-RELEASE_32_final/
diff --git a/aos/externals/WPILib/WPILib/ADXL345_I2C.cpp b/aos/externals/WPILib/WPILib/ADXL345_I2C.cpp
index 9880e0e..2a4040e 100644
--- a/aos/externals/WPILib/WPILib/ADXL345_I2C.cpp
+++ b/aos/externals/WPILib/WPILib/ADXL345_I2C.cpp
@@ -73,7 +73,7 @@
  */
 ADXL345_I2C::AllAxes ADXL345_I2C::GetAccelerations()
 {
-	AllAxes data = {0.0};
+	AllAxes data = {0.0, 0.0, 0.0};
 	INT16 rawData[3];
 	if (m_i2c)
 	{
diff --git a/aos/externals/WPILib/WPILib/ADXL345_SPI.cpp b/aos/externals/WPILib/WPILib/ADXL345_SPI.cpp
index 789448d..42d8dea 100644
--- a/aos/externals/WPILib/WPILib/ADXL345_SPI.cpp
+++ b/aos/externals/WPILib/WPILib/ADXL345_SPI.cpp
@@ -157,7 +157,7 @@
  */
 ADXL345_SPI::AllAxes ADXL345_SPI::GetAccelerations()
 {
-	AllAxes data = {0.0};
+	AllAxes data = {0.0, 0.0, 0.0};
 	INT16 rawData[3];
 	if (m_spi)
 	{
diff --git a/aos/externals/WPILib/WPILib/AnalogChannel.cpp b/aos/externals/WPILib/WPILib/AnalogChannel.cpp
index 834837f..26708c1 100644
--- a/aos/externals/WPILib/WPILib/AnalogChannel.cpp
+++ b/aos/externals/WPILib/WPILib/AnalogChannel.cpp
@@ -38,9 +38,9 @@
 	}
 
 	snprintf(buf, 64, "Analog Input %d (Module: %d)", channel, moduleNumber);
-	if (channels->Allocate((moduleNumber - 1) * kAnalogChannels + channel - 1, buf) == ~0ul)
+	if (channels->Allocate((moduleNumber - 1) * kAnalogChannels +
+                         channel - 1, buf, this) == ~0ul)
 	{
-		CloneError(channels);
 		return;
 	}
 	m_channel = channel;
@@ -86,7 +86,8 @@
  */
 AnalogChannel::~AnalogChannel()
 {
-	channels->Free((m_module->GetNumber() - 1) * kAnalogChannels + m_channel - 1);
+	channels->Free((m_module->GetNumber() - 1) * kAnalogChannels + m_channel - 1,
+                 this);
 }
 
 /**
diff --git a/aos/externals/WPILib/WPILib/AnalogModule.cpp b/aos/externals/WPILib/WPILib/AnalogModule.cpp
index d685c13..68e7940 100644
--- a/aos/externals/WPILib/WPILib/AnalogModule.cpp
+++ b/aos/externals/WPILib/WPILib/AnalogModule.cpp
@@ -14,7 +14,8 @@
 const long AnalogModule::kDefaultOversampleBits;
 const long AnalogModule::kDefaultAverageBits;
 const float AnalogModule::kDefaultSampleRate;
-SEM_ID AnalogModule::m_registerWindowSemaphore = NULL;
+// Needs to be global since the protected resource spans both module singletons.
+ReentrantSemaphore AnalogModule::m_registerWindowSemaphore;
 
 /**
  * Get an instance of an Analog Module.
@@ -71,12 +72,6 @@
 		SetAverageBits(i + 1, kDefaultAverageBits);
 		SetOversampleBits(i + 1, kDefaultOversampleBits);
 	}
-
-	if (m_registerWindowSemaphore == NULL)
-	{
-		// Needs to be global since the protected resource spans both module singletons.
-		m_registerWindowSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
-	}
 }
 
 /**
diff --git a/aos/externals/WPILib/WPILib/AnalogModule.h b/aos/externals/WPILib/WPILib/AnalogModule.h
index 3f69685..3ed44ca 100644
--- a/aos/externals/WPILib/WPILib/AnalogModule.h
+++ b/aos/externals/WPILib/WPILib/AnalogModule.h
@@ -48,7 +48,7 @@
 	virtual ~AnalogModule();
 
 private:
-	static SEM_ID m_registerWindowSemaphore;
+	static ReentrantSemaphore m_registerWindowSemaphore;
 
 	UINT32 GetNumActiveChannels();
 	UINT32 GetNumChannelsToActivate();
diff --git a/aos/externals/WPILib/WPILib/AnalogTrigger.cpp b/aos/externals/WPILib/WPILib/AnalogTrigger.cpp
index ffe45c1..2deeb54 100644
--- a/aos/externals/WPILib/WPILib/AnalogTrigger.cpp
+++ b/aos/externals/WPILib/WPILib/AnalogTrigger.cpp
@@ -21,10 +21,9 @@
 void AnalogTrigger::InitTrigger(UINT8 moduleNumber, UINT32 channel)
 {
 	Resource::CreateResourceObject(&triggers, tAnalogTrigger::kNumSystems);
-	UINT32 index = triggers->Allocate("Analog Trigger");
+	UINT32 index = triggers->Allocate("Analog Trigger", this);
 	if (index == ~0ul)
 	{
-		CloneError(triggers);
 		return;
 	}
 	m_index = (UINT8)index;
@@ -74,7 +73,7 @@
 
 AnalogTrigger::~AnalogTrigger()
 {
-	triggers->Free(m_index);
+	triggers->Free(m_index, this);
 	delete m_trigger;
 }
 
diff --git a/aos/externals/WPILib/WPILib/CAN/JaguarCANDriver.h b/aos/externals/WPILib/WPILib/CAN/JaguarCANDriver.h
index 35c82a5..0f8afe4 100644
--- a/aos/externals/WPILib/WPILib/CAN/JaguarCANDriver.h
+++ b/aos/externals/WPILib/WPILib/CAN/JaguarCANDriver.h
@@ -14,8 +14,6 @@
 #ifndef __JaguarCANDriver_h__
 #define __JaguarCANDriver_h__
 
-#include <VxWorks.h>
-
 #ifdef __cplusplus
 extern "C"
 {
diff --git a/aos/externals/WPILib/WPILib/CANJaguar.cpp b/aos/externals/WPILib/WPILib/CANJaguar.cpp
index cf03370..ec55460 100644
--- a/aos/externals/WPILib/WPILib/CANJaguar.cpp
+++ b/aos/externals/WPILib/WPILib/CANJaguar.cpp
@@ -1223,7 +1223,7 @@
 
 void CANJaguar::GetDescription(char *desc)
 {
-	sprintf(desc, "CANJaguar ID %d", m_deviceNumber);
+	snprintf(desc, 64, "CANJaguar ID %d", m_deviceNumber);
 }
 
 /**
diff --git a/aos/externals/WPILib/WPILib/ChipObject/tSystemInterface.h b/aos/externals/WPILib/WPILib/ChipObject/tSystemInterface.h
index 46786e8..d5008e1 100644
--- a/aos/externals/WPILib/WPILib/ChipObject/tSystemInterface.h
+++ b/aos/externals/WPILib/WPILib/ChipObject/tSystemInterface.h
@@ -12,9 +12,9 @@
    tSystemInterface(){}
    virtual ~tSystemInterface(){}
 
-   virtual const uint16_t getExpectedFPGAVersion()=0;
-   virtual const uint32_t getExpectedFPGARevision()=0;
-   virtual const uint32_t * const getExpectedFPGASignature()=0;
+   virtual uint16_t getExpectedFPGAVersion()=0;
+   virtual uint32_t getExpectedFPGARevision()=0;
+   virtual uint32_t * getExpectedFPGASignature()=0;
    virtual void getHardwareFpgaSignature(uint32_t *guid_ptr, tRioStatusCode *status)=0;
    virtual uint32_t getLVHandle(tRioStatusCode *status)=0;
    virtual uint32_t getHandle()=0;
diff --git a/aos/externals/WPILib/WPILib/Counter.cpp b/aos/externals/WPILib/WPILib/Counter.cpp
index a11c268..e7c17ad 100644
--- a/aos/externals/WPILib/WPILib/Counter.cpp
+++ b/aos/externals/WPILib/WPILib/Counter.cpp
@@ -20,10 +20,9 @@
 void Counter::InitCounter(Mode mode)
 {
 	Resource::CreateResourceObject(&counters, tCounter::kNumSystems);
-	UINT32 index = counters->Allocate("Counter");
+	UINT32 index = counters->Allocate("Counter", this);
 	if (index == ~0ul)
 	{
-		CloneError(counters);
 		return;
 	}
 	m_index = index;
@@ -183,7 +182,7 @@
 	}
 	delete m_counter;
 	m_counter = NULL;
-	counters->Free(m_index);
+	counters->Free(m_index, this);
 }
 
 /**
diff --git a/aos/externals/WPILib/WPILib/Dashboard.cpp b/aos/externals/WPILib/WPILib/Dashboard.cpp
index c513baf..2235b99 100644
--- a/aos/externals/WPILib/WPILib/Dashboard.cpp
+++ b/aos/externals/WPILib/WPILib/Dashboard.cpp
@@ -29,7 +29,7 @@
 {
 	m_userStatusData = new char[kMaxDashboardDataSize];
 	m_localBuffer = new char[kMaxDashboardDataSize];
-	m_localPrintBuffer = new char[kMaxDashboardDataSize * 2];
+	m_localPrintBuffer = new char[kLocalPrintBufferSize];
 	m_localPrintBuffer[0] = 0;
 	m_packPtr = m_localBuffer;
 	m_printSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
@@ -275,7 +275,7 @@
 	va_start (args, writeFmt);
 	{
 		Synchronized sync(m_printSemaphore);
-		vsprintf(m_localPrintBuffer + strlen(m_localPrintBuffer), writeFmt, args);
+		vsnprintf(m_localPrintBuffer + strlen(m_localPrintBuffer), kLocalPrintBufferSize - strlen(m_localPrintBuffer), writeFmt, args);
 		size = strlen(m_localPrintBuffer);
 	}
 	if (size > kMaxDashboardDataSize)
diff --git a/aos/externals/WPILib/WPILib/Dashboard.h b/aos/externals/WPILib/WPILib/Dashboard.h
index dfcf989..1856660 100644
--- a/aos/externals/WPILib/WPILib/Dashboard.h
+++ b/aos/externals/WPILib/WPILib/Dashboard.h
@@ -50,6 +50,7 @@
 	void Flush() {}
 private:
 	static const INT32 kMaxDashboardDataSize = USER_STATUS_DATA_SIZE - sizeof(UINT32) * 3 - sizeof(UINT8); // 13 bytes needed for 3 size parameters and the sequence number
+  static const size_t kLocalPrintBufferSize = kMaxDashboardDataSize * 2;
 
 	// Usage Guidelines...
 	DISALLOW_COPY_AND_ASSIGN(Dashboard);
diff --git a/aos/externals/WPILib/WPILib/DigitalModule.cpp b/aos/externals/WPILib/WPILib/DigitalModule.cpp
index 3e7f728..d715c65 100644
--- a/aos/externals/WPILib/WPILib/DigitalModule.cpp
+++ b/aos/externals/WPILib/WPILib/DigitalModule.cpp
@@ -63,7 +63,7 @@
 	if (m_fpgaDIO->readLoopTiming(&localStatus) != kExpectedLoopTiming)
 	{
 		char err[128];
-		sprintf(err, "DIO LoopTiming: %d, expecting: %d\n", m_fpgaDIO->readLoopTiming(&localStatus), kExpectedLoopTiming);
+		snprintf(err, sizeof(err), "DIO LoopTiming: %d, expecting: %d\n", m_fpgaDIO->readLoopTiming(&localStatus), kExpectedLoopTiming);
 		wpi_setWPIErrorWithContext(LoopTimingError, err);
 	}
 	m_fpgaDIO->writePWMConfig_Period(PWM::kDefaultPwmPeriod, &localStatus);
@@ -154,18 +154,7 @@
  */
 void DigitalModule::SetRelayForward(UINT32 channel, bool on)
 {
-	tRioStatusCode localStatus = NiFpga_Status_Success;
-	CheckRelayChannel(channel);
-	{
-		Synchronized sync(m_relaySemaphore);
-		UINT8 forwardRelays = m_fpgaDIO->readSlowValue_RelayFwd(&localStatus);
-		if (on)
-			forwardRelays |= 1 << (channel - 1);
-		else
-			forwardRelays &= ~(1 << (channel - 1));
-		m_fpgaDIO->writeSlowValue_RelayFwd(forwardRelays, &localStatus);
-	}
-	wpi_setError(localStatus);
+  SetRelaysForward(1 << (channel - 1), on ? 0xFF : 0x00);
 }
 
 /**
@@ -175,18 +164,47 @@
  */
 void DigitalModule::SetRelayReverse(UINT32 channel, bool on)
 {
-	tRioStatusCode localStatus = NiFpga_Status_Success;
-	CheckRelayChannel(channel);
-	{
-		Synchronized sync(m_relaySemaphore);
-		UINT8 reverseRelays = m_fpgaDIO->readSlowValue_RelayRev(&localStatus);
-		if (on)
-			reverseRelays |= 1 << (channel - 1);
-		else
-			reverseRelays &= ~(1 << (channel - 1));
-		m_fpgaDIO->writeSlowValue_RelayRev(reverseRelays, &localStatus);
-	}
-	wpi_setError(localStatus);
+  SetRelaysReverse(1 << (channel - 1), on ? 0xFF : 0x00);
+}
+
+/**
+ * Set the state of multiple relays at the same time.
+ * For both parameters, 0b100000000 is channel 1 and 0b00000001 is channel 8.
+ * @param mask which relays to set
+ * @param values what to set the relays to
+ */
+void DigitalModule::SetRelaysForward(UINT8 mask, UINT8 values) {
+  tRioStatusCode localStatus = NiFpga_Status_Success;
+  {
+    Synchronized sync(m_relaySemaphore);
+    UINT8 current = m_fpgaDIO->readSlowValue_RelayFwd(&localStatus);
+    // Clearr all of the bits that we're messing with first.
+    current &= ~mask;
+    // Then set only the ones that are supposed to be set.
+    current |= (mask & values);
+    m_fpgaDIO->writeSlowValue_RelayFwd(current, &localStatus);
+  }
+  wpi_setError(localStatus);
+}
+
+/**
+ * Set the state of multiple relays at the same time.
+ * For both parameters, 0b100000000 is channel 1 and 0b00000001 is channel 8.
+ * @param mask which relays to set
+ * @param values what to set the relays to
+ */
+void DigitalModule::SetRelaysReverse(UINT8 mask, UINT8 values) {
+  tRioStatusCode localStatus = NiFpga_Status_Success;
+  {
+    Synchronized sync(m_relaySemaphore);
+    UINT8 current = m_fpgaDIO->readSlowValue_RelayRev(&localStatus);
+    // Clearr all of the bits that we're messing with first.
+    current &= ~mask;
+    // Then set only the ones that are supposed to be set.
+    current |= (mask & values);
+    m_fpgaDIO->writeSlowValue_RelayRev(current, &localStatus);
+  }
+  wpi_setError(localStatus);
 }
 
 /**
@@ -248,7 +266,8 @@
 {
 	char buf[64];
 	snprintf(buf, 64, "DIO %d (Module %d)", channel, m_moduleNumber);
-	if (DIOChannels->Allocate(kDigitalChannels * (m_moduleNumber - 1) + channel - 1, buf) == ~0ul) return false;
+	if (DIOChannels->Allocate(kDigitalChannels * (m_moduleNumber - 1) +
+                            channel - 1, buf, this) == ~0ul) return false;
 	tRioStatusCode localStatus = NiFpga_Status_Success;
 	{
 		Synchronized sync(m_digitalSemaphore);
@@ -276,7 +295,29 @@
  */
 void DigitalModule::FreeDIO(UINT32 channel)
 {
-	DIOChannels->Free(kDigitalChannels * (m_moduleNumber - 1) + channel - 1);
+	DIOChannels->Free(kDigitalChannels * (m_moduleNumber - 1) + channel - 1,
+                    this);
+}
+
+/**
+ * Write multiple digital I/O bits to the FPGA at the same time.
+ * For both parameters, 0x0001 is channel 16 and 0x8000 is channel 1.
+ *
+ * @param mask Which bits to modify.
+ * @param values What to set all of the bits in mask to.
+ */
+void DigitalModule::SetDIOs(UINT16 mask, UINT16 values) {
+  tRioStatusCode localStatus = NiFpga_Status_Success;
+  {
+    Synchronized sync(m_digitalSemaphore);
+    UINT16 current = m_fpgaDIO->readDO(&localStatus);
+    // Clear all of the bits that we're messing with first.
+    current &= ~mask;
+    // Then set only the ones that are supposed to be set.
+    current |= (mask & values);
+    m_fpgaDIO->writeDO(current, &localStatus);
+  }
+  wpi_setError(localStatus);
 }
 
 /**
@@ -286,29 +327,9 @@
  * @param channel The Digital I/O channel
  * @param value The state to set the digital channel (if it is configured as an output)
  */
-void DigitalModule::SetDIO(UINT32 channel, short value)
+void DigitalModule::SetDIO(UINT32 channel, bool value)
 {
-	if (value != 0 && value != 1)
-	{
-		wpi_setWPIError(NonBinaryDigitalValue);
-		if (value != 0)
-			value = 1;
-	}
-	tRioStatusCode localStatus = NiFpga_Status_Success;
-	{
-		Synchronized sync(m_digitalSemaphore);
-		UINT16 currentDIO = m_fpgaDIO->readDO(&localStatus);
-		if(value == 0)
-		{
-			currentDIO = currentDIO & ~(1 << RemapDigitalChannel(channel - 1));
-		}
-		else if (value == 1)
-		{
-			currentDIO = currentDIO | (1 << RemapDigitalChannel(channel - 1));
-		} 
-		m_fpgaDIO->writeDO(currentDIO, &localStatus);
-	}
-	wpi_setError(localStatus);
+  SetDIOs(1 << RemapDigitalChannel(channel - 1), value ? 0xFFFF : 0x0000);
 }
 
 /**
@@ -421,7 +442,7 @@
 
 /**
  * Allocate a DO PWM Generator.
- * Allocate PWM generators so that they are not accidently reused.
+ * Allocate PWM generators so that they are not accidentally reused.
  * 
  * @return PWM Generator refnum
  */
@@ -429,7 +450,7 @@
 {
 	char buf[64];
 	snprintf(buf, 64, "DO_PWM (Module: %d)", m_moduleNumber);
-	return DO_PWMGenerators[(m_moduleNumber - 1)]->Allocate(buf);
+	return DO_PWMGenerators[(m_moduleNumber - 1)]->Allocate(buf, this);
 }
 
 /**
@@ -440,7 +461,7 @@
 void DigitalModule::FreeDO_PWM(UINT32 pwmGenerator)
 {
 	if (pwmGenerator == ~0ul) return;
-	DO_PWMGenerators[(m_moduleNumber - 1)]->Free(pwmGenerator);
+	DO_PWMGenerators[(m_moduleNumber - 1)]->Free(pwmGenerator, this);
 }
 
 /**
@@ -461,7 +482,7 @@
 }
 
 /**
- * Configure which DO channel the PWM siganl is output on
+ * Configure which DO channel the PWM signal is output on
  * 
  * @param pwmGenerator The generator index reserved by AllocateDO_PWM()
  * @param channel The Digital Output channel to output on
diff --git a/aos/externals/WPILib/WPILib/DigitalModule.h b/aos/externals/WPILib/WPILib/DigitalModule.h
index e80beb6..44f617f 100644
--- a/aos/externals/WPILib/WPILib/DigitalModule.h
+++ b/aos/externals/WPILib/WPILib/DigitalModule.h
@@ -29,13 +29,16 @@
 	void SetPWMPeriodScale(UINT32 channel, UINT32 squelchMask);
 	void SetRelayForward(UINT32 channel, bool on);
 	void SetRelayReverse(UINT32 channel, bool on);
+  void SetRelaysForward(UINT8 mask, UINT8 values);
+  void SetRelaysReverse(UINT8 mask, UINT8 values);
 	bool GetRelayForward(UINT32 channel);
 	UINT8 GetRelayForward();
 	bool GetRelayReverse(UINT32 channel);
 	UINT8 GetRelayReverse();
 	bool AllocateDIO(UINT32 channel, bool input);
 	void FreeDIO(UINT32 channel);
-	void SetDIO(UINT32 channel, short value);
+  void SetDIOs(UINT16 mask, UINT16 values);
+	void SetDIO(UINT32 channel, bool value);
 	bool GetDIO(UINT32 channel);
 	UINT16 GetDIO();
 	bool GetDIODirection(UINT32 channel);
diff --git a/aos/externals/WPILib/WPILib/DigitalOutput.cpp b/aos/externals/WPILib/WPILib/DigitalOutput.cpp
index a571066..4f45ee7 100644
--- a/aos/externals/WPILib/WPILib/DigitalOutput.cpp
+++ b/aos/externals/WPILib/WPILib/DigitalOutput.cpp
@@ -214,10 +214,9 @@
 void DigitalOutput::RequestInterrupts(tInterruptHandler handler, void *param)
 {
 	if (StatusIsFatal()) return;
-	UINT32 index = interruptsResource->Allocate("Sync Interrupt");
+	UINT32 index = interruptsResource->Allocate("Sync Interrupt", this);
 	if (index == ~0ul)
 	{
-		CloneError(interruptsResource);
 		return;
 	}
 	m_interruptIndex = index;
@@ -245,10 +244,9 @@
 void DigitalOutput::RequestInterrupts()
 {
 	if (StatusIsFatal()) return;
-	UINT32 index = interruptsResource->Allocate("Sync Interrupt");
+	UINT32 index = interruptsResource->Allocate("Sync Interrupt", this);
 	if (index == ~0ul)
 	{
-		CloneError(interruptsResource);
 		return;
 	}
 	m_interruptIndex = index;
diff --git a/aos/externals/WPILib/WPILib/DigitalSource.cpp b/aos/externals/WPILib/WPILib/DigitalSource.cpp
index 3c1e3a8..862b439 100644
--- a/aos/externals/WPILib/WPILib/DigitalSource.cpp
+++ b/aos/externals/WPILib/WPILib/DigitalSource.cpp
@@ -24,7 +24,7 @@
 	{
 		delete m_manager;
 		delete m_interrupt;
-		interruptsResource->Free(m_interruptIndex);
+		interruptsResource->Free(m_interruptIndex, this);
 	}
 }
 
@@ -39,10 +39,9 @@
 void DigitalSource::RequestInterrupts(tInterruptHandler handler, void *param)
 {
 	if (StatusIsFatal()) return;
-	UINT32 index = interruptsResource->Allocate("Async Interrupt");
+	UINT32 index = interruptsResource->Allocate("Async Interrupt", this);
 	if (index == ~0ul)
 	{
-		CloneError(interruptsResource);
 		return;
 	}
 	m_interruptIndex = index;
@@ -70,10 +69,9 @@
 void DigitalSource::RequestInterrupts()
 {
 	if (StatusIsFatal()) return;
-	UINT32 index = interruptsResource->Allocate("Sync Interrupt");
+	UINT32 index = interruptsResource->Allocate("Sync Interrupt", this);
 	if (index == ~0ul)
 	{
-		CloneError(interruptsResource);
 		return;
 	}
 	m_interruptIndex = index;
diff --git a/aos/externals/WPILib/WPILib/DoubleSolenoid.cpp b/aos/externals/WPILib/WPILib/DoubleSolenoid.cpp
index d05c7ff..4b3e473 100644
--- a/aos/externals/WPILib/WPILib/DoubleSolenoid.cpp
+++ b/aos/externals/WPILib/WPILib/DoubleSolenoid.cpp
@@ -37,15 +37,15 @@
 	Resource::CreateResourceObject(&m_allocated, tSolenoid::kNumDO7_0Elements * kSolenoidChannels);
 
 	snprintf(buf, 64, "Solenoid %d (Module %d)", m_forwardChannel, m_moduleNumber);
-	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels + m_forwardChannel - 1, buf) == ~0ul)
+	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels +
+                            m_forwardChannel - 1, buf, this) == ~0ul)
 	{
-		CloneError(m_allocated);
 		return;
 	}
 	snprintf(buf, 64, "Solenoid %d (Module %d)", m_reverseChannel, m_moduleNumber);
-	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels + m_reverseChannel - 1, buf) == ~0ul)
+	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels +
+                            m_reverseChannel - 1, buf, this) == ~0ul)
 	{
-		CloneError(m_allocated);
 		return;
 	}
 	m_forwardMask = 1 << (m_forwardChannel - 1);
@@ -90,11 +90,10 @@
  */
 DoubleSolenoid::~DoubleSolenoid()
 {
-	if (CheckSolenoidModule(m_moduleNumber))
-	{
-		m_allocated->Free((m_moduleNumber - 1) * kSolenoidChannels + m_forwardChannel - 1);
-		m_allocated->Free((m_moduleNumber - 1) * kSolenoidChannels + m_reverseChannel - 1);
-	}
+	m_allocated->Free((m_moduleNumber - 1) * kSolenoidChannels +
+                    m_forwardChannel - 1, this);
+	m_allocated->Free((m_moduleNumber - 1) * kSolenoidChannels +
+                    m_reverseChannel - 1, this);
 }
 
 /**
diff --git a/aos/externals/WPILib/WPILib/DoubleSolenoid.h b/aos/externals/WPILib/WPILib/DoubleSolenoid.h
index f9920a1..a4cd03a 100644
--- a/aos/externals/WPILib/WPILib/DoubleSolenoid.h
+++ b/aos/externals/WPILib/WPILib/DoubleSolenoid.h
@@ -38,7 +38,7 @@
 	ITable * GetTable();
 
 private:
-	virtual void InitSolenoid();
+	void InitSolenoid();
 
 	UINT32 m_forwardChannel; ///< The forward channel on the module to control.
 	UINT32 m_reverseChannel; ///< The reverse channel on the module to control.
diff --git a/aos/externals/WPILib/WPILib/DriverStation.cpp b/aos/externals/WPILib/WPILib/DriverStation.cpp
index ffe0e66..e71ab90 100644
--- a/aos/externals/WPILib/WPILib/DriverStation.cpp
+++ b/aos/externals/WPILib/WPILib/DriverStation.cpp
@@ -159,7 +159,8 @@
 void DriverStation::GetData()
 {
 	static bool lastEnabled = false;
-	getCommonControlData(m_controlData, WAIT_FOREVER);
+	// Have to const_cast away the volatile.
+	getCommonControlData(const_cast<FRCCommonControlData *>(m_controlData), WAIT_FOREVER);
 	if (!lastEnabled && IsEnabled()) 
 	{
 		// If starting teleop, assume that autonomous just took up 15 seconds
@@ -364,6 +365,7 @@
 	if (channel < 1 || channel > 8)
 		wpi_setWPIErrorWithContext(ParameterOutOfRange, "channel must be between 1 and 8");
 
+	// TODO: fix the lack of thread safety here
 	static UINT8 reported_mask = 0;
 	if (!(reported_mask & (1 >> channel)))
 	{
@@ -388,32 +390,79 @@
 	return ((m_digitalOut >> (channel-1)) & 0x1) ? true : false;;
 }
 
+/**
+ * @return Whether or not the robot is currently enabled by the field controls.
+ */
 bool DriverStation::IsEnabled()
 {
 	return m_controlData->enabled;
 }
 
+/**
+ * @return Whether or not the robot is currently disabled by the field controls.
+ */
 bool DriverStation::IsDisabled()
 {
 	return !m_controlData->enabled;
 }
 
+/**
+ * Determines if the robot is currently in autonomous mode. Does not check
+ * whether the robot is enabled.
+ * @return Whether or not the robot is currently in autonomous mode.
+ */
 bool DriverStation::IsAutonomous()
 {
 	return m_controlData->autonomous;
 }
 
+/**
+ * Determines if the robot is currently in teleoperated mode. Does not check
+ * whether the robot is enabled.
+ * @return Whether or not the robot is currently in teleoperated mode.
+ */
 bool DriverStation::IsOperatorControl()
 {
 	return !(m_controlData->autonomous || m_controlData->test);
 }
 
+/**
+ * Determines if the robot is currently in test mode. Does not check
+ * whether the robot is enabled.
+ * @return Whether or not the robot is currently in test mode.
+ */
 bool DriverStation::IsTest()
 {
 	return m_controlData->test;
 }
 
 /**
+ * @return What state the robot is currently in.
+ */
+DriverStation::FMSState DriverStation::GetCurrentState() {
+  UINT8 control_at_start = m_controlData->control;
+  if (IsDisabled()) {
+    return FMSState::kDisabled;
+    // Or else it must be enabled (for all of the other ones).
+  } else if (IsAutonomous()) {
+    return FMSState::kAutonomous;
+  } else if (IsTest()) {
+    return FMSState::kTestMode;
+  } else if (IsOperatorControl()) {
+    return FMSState::kTeleop;
+  } else {
+    // If we didn't get another packet in the mean time.
+    if (m_controlData->control == control_at_start) {
+      wpi_setWPIErrorWithContext(IncompatibleState, "Unknown FMS State");
+      return FMSState::kDisabled;
+    } else {
+      // The data changed out from under us. Try again.
+      return GetCurrentState();
+    }
+  }
+}
+
+/**
  * Has a new control packet from the driver station arrived since the last time this function was called?
  * Warning: If you call this function from more than one place at the same time,
  * you will not get the get the intended behavior
diff --git a/aos/externals/WPILib/WPILib/DriverStation.h b/aos/externals/WPILib/WPILib/DriverStation.h
index acd9b16..fffa675 100644
--- a/aos/externals/WPILib/WPILib/DriverStation.h
+++ b/aos/externals/WPILib/WPILib/DriverStation.h
@@ -23,7 +23,15 @@
 public:
 	enum Alliance {kRed, kBlue, kInvalid};
 
-	virtual ~DriverStation();
+  // Represents all of the states that FMS thinks of a robot as being in.
+  // NOTE: All of the ones except kDisabled mean that the robot is enabled too.
+  enum FMSState {
+    kDisabled,
+    kAutonomous,
+    kTeleop,
+    kTestMode,
+  };
+
 	static DriverStation *GetInstance();
 
 	static const UINT32 kBatteryModuleNumber = 1;
@@ -41,9 +49,10 @@
 
 	bool IsEnabled();
 	bool IsDisabled();
-    bool IsAutonomous();
+  bool IsAutonomous();
 	bool IsOperatorControl();
-    bool IsTest();
+  bool IsTest();
+  FMSState GetCurrentState();
 	bool IsNewControlData();
 	bool IsFMSAttached();
 
@@ -96,6 +105,7 @@
 
 protected:
 	DriverStation();
+	virtual ~DriverStation();
 
 	void GetData();
 	void SetData();
@@ -109,7 +119,10 @@
 
 	void Run();
 
-	struct FRCCommonControlData *m_controlData;
+  // Volatile because it gets modified by GetData() in a separate task. Be
+  // careful using values out of here (2-byte accesses are safe as long as
+  // they're aligned, which all of the ones in here should be).
+	volatile struct FRCCommonControlData *m_controlData;
 	UINT8 m_digitalOut;
 	AnalogChannel *m_batteryChannel;
 	SEM_ID m_statusDataSemaphore;
diff --git a/aos/externals/WPILib/WPILib/DriverStationLCD.h b/aos/externals/WPILib/WPILib/DriverStationLCD.h
index 3ea90a5..1a3731f 100644
--- a/aos/externals/WPILib/WPILib/DriverStationLCD.h
+++ b/aos/externals/WPILib/WPILib/DriverStationLCD.h
@@ -25,7 +25,6 @@
 	static const INT32 kNumLines = 6;
 	enum Line {kMain_Line6=0, kUser_Line1=0, kUser_Line2=1, kUser_Line3=2, kUser_Line4=3, kUser_Line5=4, kUser_Line6=5};
 
-	virtual ~DriverStationLCD();
 	static DriverStationLCD *GetInstance();
 
 	void UpdateLCD();
@@ -38,6 +37,7 @@
 
 protected:
 	DriverStationLCD();
+	virtual ~DriverStationLCD();
 
 private:
 	static void InitTask(DriverStationLCD *ds);
diff --git a/aos/externals/WPILib/WPILib/Encoder.cpp b/aos/externals/WPILib/WPILib/Encoder.cpp
index cdf1dba..cfb96c9 100644
--- a/aos/externals/WPILib/WPILib/Encoder.cpp
+++ b/aos/externals/WPILib/WPILib/Encoder.cpp
@@ -27,14 +27,11 @@
 {
 	m_encodingType = encodingType;
 	tRioStatusCode localStatus = NiFpga_Status_Success;
-	switch (encodingType)
-	{
-	case k4X:
+  if (encodingType == k4X) {
 		Resource::CreateResourceObject(&quadEncoders, tEncoder::kNumSystems);
-		UINT32 index = quadEncoders->Allocate("4X Encoder");
+		UINT32 index = quadEncoders->Allocate("4X Encoder", this);
 		if (index == ~0ul)
 		{
-			CloneError(quadEncoders);
 			return;
 		}
 		if (m_aSource->StatusIsFatal())
@@ -59,12 +56,9 @@
 		m_encoder->writeConfig_Reverse(reverseDirection, &localStatus);
 		m_encoder->writeTimerConfig_AverageSize(4, &localStatus);
 		m_counter = NULL;
-		break;
-	case k1X:
-	case k2X:
+  } else {
 		m_counter = new Counter(m_encodingType, m_aSource, m_bSource, reverseDirection);
 		m_index = m_counter->GetIndex();
-		break;
 	}
 	m_distancePerPulse = 1.0;
 	m_pidSource = kDistance;
@@ -195,7 +189,7 @@
 	}
 	else
 	{
-		quadEncoders->Free(m_index);
+		quadEncoders->Free(m_index, this);
 		delete m_encoder;
 	}
 }
diff --git a/aos/externals/WPILib/WPILib/Error.cpp b/aos/externals/WPILib/WPILib/Error.cpp
index 30f0cbc..9e83de7 100644
--- a/aos/externals/WPILib/WPILib/Error.cpp
+++ b/aos/externals/WPILib/WPILib/Error.cpp
@@ -25,8 +25,32 @@
 Error::~Error()
 {}
 
-void Error::Clone(Error &error)
+/**
+ * Clones another error into this if this is currently clear. If not, does
+ * nothing.
+ * This is necessary because just using "if (!IsClear()) Clone(error)" has a
+ * race condition which this method does not.
+ * Cloning 2 errors into each other at the same time can lead to deadlocks!
+ */
+void Error::CloneIfClear(const Error &error) {
+  Synchronized sync(m_semaphore);
+  if (IsClear()) {
+    DoClone(error);
+  }
+}
+
+/**
+ * Clones another error into this object.
+ * Cloning 2 errors into each other at the same time can lead to deadlocks!
+ */
+void Error::Clone(const Error &error) {
+  Synchronized sync(m_semaphore);
+  DoClone(error);
+}
+
+void Error::DoClone(const Error &error)
 {
+  Synchronized sync(error.m_semaphore);
 	m_code = error.m_code;
 	m_message = error.m_message;
 	m_filename = error.m_filename;
@@ -36,17 +60,19 @@
 	m_timestamp = error.m_timestamp;
 }
 
+bool Error::IsClear() const { return GetCode() == 0; }
+
 Error::Code Error::GetCode() const
 {	return m_code;  }
 
-const char * Error::GetMessage() const
-{	return m_message.c_str();  }
+std::string Error::GetMessage() const
+{	return m_message;  }
 
-const char * Error::GetFilename() const
-{	return m_filename.c_str();  }
+std::string Error::GetFilename() const
+{	return m_filename;  }
 
-const char * Error::GetFunction() const
-{	return m_function.c_str();  }
+std::string Error::GetFunction() const
+{	return m_function;  }
 
 UINT32 Error::GetLineNumber() const
 {	return m_lineNumber;  }
@@ -57,8 +83,10 @@
 double Error::GetTime() const
 {	return m_timestamp;  }
 
-void Error::Set(Code code, const char* contextMessage, const char* filename, const char* function, UINT32 lineNumber, const ErrorBase* originatingObject)
-{
+void Error::Set(Code code, const char* contextMessage, const char* filename,
+                const char* function, UINT32 lineNumber,
+                const ErrorBase* originatingObject)  {
+  Synchronized sync(m_semaphore);
 	m_code = code;
 	m_message = contextMessage;
 	m_filename = filename;
@@ -69,39 +97,40 @@
 
 	Report();
 
-	if (m_suspendOnErrorEnabled) taskSuspend(0);
+	if (m_suspendOnErrorEnabled) taskSuspend(0 /*self*/);
 }
 
-void Error::Report()
+void Error::Report() const
 {
 	// Error string buffers
-	char *error = new char[256];
-	char *error_with_code = new char[256];
+	char error[256];
+	char error_with_code[256];
 
 	// Build error strings
-	if (m_code != -1)
+	if (m_code != -1 && m_code != 1)
 	{
-		snprintf(error, 256, "%s: status = %d (0x%08X) %s ...in %s() in %s at line %d\n",
-				m_code < 0 ? "ERROR" : "WARNING", (INT32)m_code, (UINT32)m_code, m_message.c_str(),
-				m_function.c_str(), m_filename.c_str(), m_lineNumber);
-		sprintf(error_with_code,"<Code>%d %s", (INT32)m_code, error);
+		snprintf(error, sizeof(error),
+             "%s: status = %d (0x%08X) %s ...in %s() in %s at line %d\n",
+				     m_code < 0 ? "ERROR" : "WARNING", (INT32)m_code,
+             (UINT32)m_code, m_message.c_str(),
+				     m_function.c_str(), m_filename.c_str(), m_lineNumber);
+		snprintf(error_with_code, sizeof(error_with_code),
+             "<Code>%d %s", (INT32)m_code, error);
 	} else {
-		snprintf(error, 256, "ERROR: %s ...in %s() in %s at line %d\n", m_message.c_str(),
-				m_function.c_str(), m_filename.c_str(), m_lineNumber);
-		strcpy(error_with_code, error);
+		snprintf(error, sizeof(error),
+             "%s: %s ...in %s() in %s at line %d\n",
+             m_code < 0 ? "ERROR" : "WARNING", m_message.c_str(),
+				     m_function.c_str(), m_filename.c_str(), m_lineNumber);
+		strncpy(error_with_code, error, sizeof(error_with_code));
 	}
 	// TODO: Add logging to disk
 
 	// Send to the DriverStation
 	setErrorData(error_with_code, strlen(error_with_code), 100);
 
-	delete [] error_with_code;
-
 	// Print to console
 	printf("\n\n>>>>%s", error);
 
-	delete [] error;
-
 	if (m_stackTraceEnabled)
 	{
 		printf("-----------<Stack Trace>----------------\n");
@@ -111,6 +140,7 @@
 
 void Error::Clear()
 {
+  Synchronized sync(m_semaphore);
 	m_code = 0;
 	m_message = "";
 	m_filename = "";
diff --git a/aos/externals/WPILib/WPILib/Error.h b/aos/externals/WPILib/WPILib/Error.h
index a80fe06..9636262 100644
--- a/aos/externals/WPILib/WPILib/Error.h
+++ b/aos/externals/WPILib/WPILib/Error.h
@@ -10,37 +10,55 @@
 #include "Base.h"
 #include "ChipObject/NiRio.h"
 #include <string>
-#include <vxWorks.h>
+#include "Synchronized.h"
 
 //  Forward declarations
 class ErrorBase;
 
 /**
- * Error object represents a library error.
+ * Represents an error or warning.
+ *
+ * All methods that can change instance data are protected by a lock so
+ * that it is safe to call any methods from multiple tasks at the same time.
  */
 class Error
 {
 public:
+  // -1 is other error, 1 is other warning.
 	typedef tRioStatusCode Code;
 
 	Error();
 	~Error();
-	void Clone(Error &error);
-	Code GetCode() const;
-	const char *GetMessage() const;
-	const char *GetFilename() const;
-	const char *GetFunction() const;
-	UINT32 GetLineNumber() const;
-	const ErrorBase* GetOriginatingObject() const;
-	double GetTime() const;
+
+	void CloneIfClear(const Error &error);
+  void Clone(const Error &error);
 	void Clear();
 	void Set(Code code, const char* contextMessage, const char* filename,
 		const char *function, UINT32 lineNumber, const ErrorBase* originatingObject);
+
+  bool IsClear() const;
+	Code GetCode() const;
+  // Have to return by value to avoid race conditions using the result for all
+  // of these methods.
+  std::string GetMessage() const;
+  std::string GetFilename() const;
+  std::string GetFunction() const;
+	UINT32 GetLineNumber() const;
+	const ErrorBase* GetOriginatingObject() const;
+	double GetTime() const;
+
+  // Enable or disable printing out a stack trace on the console whenever there
+  // is an error.
 	static void EnableStackTrace(bool enable) { m_stackTraceEnabled=enable; }
+  // Enable or disable having any task that gets an error suspend itself.
 	static void EnableSuspendOnError(bool enable) { m_suspendOnErrorEnabled=enable; }
 
 private:
-	void Report();
+  // Deals with notifying other code of this error.
+	void Report() const;
+  // Actually implements cloning.
+  // Does not lock m_semaphore, so callers must.
+  void DoClone(const Error &error);
 
 	Code m_code;
 	std::string m_message;
@@ -49,6 +67,10 @@
 	UINT32 m_lineNumber;
 	const ErrorBase* m_originatingObject;
 	double m_timestamp;
+  // Used for protecting all modifications to instance data.
+  // This means that all non-const methods should lock this for (at least most)
+  // of their implementations!
+  ReentrantSemaphore m_semaphore;
 
 	static bool m_stackTraceEnabled;
 	static bool m_suspendOnErrorEnabled;
diff --git a/aos/externals/WPILib/WPILib/ErrorBase.cpp b/aos/externals/WPILib/WPILib/ErrorBase.cpp
index 2722963..5f766c7 100644
--- a/aos/externals/WPILib/WPILib/ErrorBase.cpp
+++ b/aos/externals/WPILib/WPILib/ErrorBase.cpp
@@ -14,8 +14,8 @@
 #include <symLib.h>
 #include <sysSymTbl.h>
 
-SEM_ID ErrorBase::_globalErrorMutex = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
 Error ErrorBase::_globalError;
+
 /**
  * @brief Initialize the instance status to 0 for now.
  */
@@ -26,15 +26,10 @@
 {}
 
 /**
- * @brief Retrieve the current error.
- * Get the current error information associated with this sensor.
+ * @brief Retrieve the error associated this object.
+ * Get the error information associated with this sensor.
  */
-Error& ErrorBase::GetError()
-{
-	return m_error;
-}
-
-const Error& ErrorBase::GetError() const
+Error& ErrorBase::GetError() const
 {
 	return m_error;
 }
@@ -48,7 +43,10 @@
 }
 
 /**
- * @brief Set error information associated with a C library call that set an error to the "errno" global variable.
+ * @brief Set error information associated with a C library call that set an
+ * error to the "errno" "global variable" (it's really a macro that calls a
+ * function under VxWorks so that it's thread safe).
+ * Will still set an error even if errno is 0.
  * 
  * @param contextMessage A custom message from the code that set the error.
  * @param filename Filename of the error source
@@ -62,7 +60,7 @@
 	int errNo = errnoGet();
 	if (errNo == 0)
 	{
-		sprintf(err, "OK: %s", contextMessage);
+		snprintf(err, sizeof(err), "OK: %s", contextMessage);
 	}
 	else
 	{
@@ -71,24 +69,21 @@
 		SYM_TYPE ptype;
 		symFindByValue(statSymTbl, errNo, statName, &pval, &ptype);
 		if (pval != errNo)
-			snprintf(err, 256, "Unknown errno 0x%08X: %s", errNo, contextMessage);
+			snprintf(err, sizeof(err), "Unknown errno 0x%08X: %s", errNo, contextMessage);
 		else
-			snprintf(err, 256, "%s (0x%08X): %s", statName, errNo, contextMessage);
+			snprintf(err, sizeof(err), "%s (0x%08X): %s", statName, errNo, contextMessage);
 		delete [] statName;
 	}
 
 	//  Set the current error information for this object.
 	m_error.Set(-1, err, filename, function, lineNumber, this);
 
-	// Update the global error if there is not one already set.
-	Synchronized mutex(_globalErrorMutex);
-	if (_globalError.GetCode() == 0) {
-		_globalError.Clone(m_error);
-	}
+  _globalError.CloneIfClear(m_error);
 }
 
 /**
  * @brief Set the current error information associated from the nivision Imaq API.
+ * Does nothing of success is > 0.
  * 
  * @param success The return from the function
  * @param contextMessage A custom message from the code that set the error.
@@ -101,21 +96,18 @@
 	//  If there was an error
 	if (success <= 0) {
 		char err[256];
-		sprintf(err, "%s: %s", contextMessage, imaqGetErrorText(imaqGetLastError()));
+		snprintf(err, sizeof(err), "%s: %s", contextMessage, imaqGetErrorText(imaqGetLastError()));
 
 		//  Set the current error information for this object.
 		m_error.Set(imaqGetLastError(), err, filename, function, lineNumber, this);
 
-		// Update the global error if there is not one already set.
-		Synchronized mutex(_globalErrorMutex);
-		if (_globalError.GetCode() == 0) {
-			_globalError.Clone(m_error);
-		}
+    _globalError.CloneIfClear(m_error);
 	}
 }
 
 /**
- * @brief Set the current error information associated with this sensor.
+ * @brief Set the current error information associated with this object.
+ * Does nothing if code is 0.
  * 
  * @param code The error code
  * @param contextMessage A custom message from the code that set the error.
@@ -131,16 +123,12 @@
 		//  Set the current error information for this object.
 		m_error.Set(code, contextMessage, filename, function, lineNumber, this);
 
-		// Update the global error if there is not one already set.
-		Synchronized mutex(_globalErrorMutex);
-		if (_globalError.GetCode() == 0) {
-			_globalError.Clone(m_error);
-		}
+    _globalError.CloneIfClear(m_error);
 	}
 }
 
 /**
- * @brief Set the current error information associated with this sensor.
+ * @brief Set the current error information associated with this object.
  * 
  * @param errorMessage The error message from WPIErrors.h
  * @param contextMessage A custom message from the code that set the error.
@@ -152,19 +140,15 @@
 		const char* filename, const char* function, UINT32 lineNumber) const
 {
 	char err[256];
-	sprintf(err, "%s: %s", errorMessage, contextMessage);
+	snprintf(err, sizeof(err), "%s: %s", errorMessage, contextMessage);
 
 	//  Set the current error information for this object.
 	m_error.Set(-1, err, filename, function, lineNumber, this);
 
-	// Update the global error if there is not one already set.
-	Synchronized mutex(_globalErrorMutex);
-	if (_globalError.GetCode() == 0) {
-		_globalError.Clone(m_error);
-	}
+  _globalError.CloneIfClear(m_error);
 }
 
-void ErrorBase::CloneError(ErrorBase *rhs) const
+void ErrorBase::CloneError(const ErrorBase *rhs) const
 {
 	m_error.Clone(rhs->GetError());
 }
@@ -179,37 +163,49 @@
 	return m_error.GetCode() < 0;
 }
 
+/**
+ * @brief Set the current global error information.
+ * Does nothing if code is 0.
+ * TODO: think about getting rid of this because nothing uses it any more
+ *
+ * @param code The error code
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
 void ErrorBase::SetGlobalError(Error::Code code, const char *contextMessage,
 		const char* filename, const char* function, UINT32 lineNumber)
 {
-	//  If there was an error
-	if (code != 0) {
-		Synchronized mutex(_globalErrorMutex);
-
-		//  Set the current error information for this object.
-		_globalError.Set(code, contextMessage, filename, function, lineNumber, NULL);
-	}
+  if (code != 0) {
+	  //  Set the current error information for this object.
+	  _globalError.Set(code, contextMessage, filename, function, lineNumber, NULL);
+  }
 }
 
+/**
+ * @brief Set the current global error information.
+ *
+ * @param errorMessage The error message from WPIErrors.h
+ * @param contextMessage A custom message from the code that set the error.
+ * @param filename Filename of the error source
+ * @param function Function of the error source
+ * @param lineNumber Line number of the error source
+ */
 void ErrorBase::SetGlobalWPIError(const char *errorMessage, const char *contextMessage,
         const char* filename, const char* function, UINT32 lineNumber)
 {
 	char err[256];
-	sprintf(err, "%s: %s", errorMessage, contextMessage);
+	snprintf(err, sizeof(err), "%s: %s", errorMessage, contextMessage);
 
-	Synchronized mutex(_globalErrorMutex);
-	if (_globalError.GetCode() != 0) {
-		_globalError.Clear();
-	}
 	_globalError.Set(-1, err, filename, function, lineNumber, NULL);
 }
 
 /**
-  * Retrieve the current global error.    
+  * Retrieve the global error.
 */
-Error& ErrorBase::GetGlobalError()
+const Error& ErrorBase::GetGlobalError()
 {
-	Synchronized mutex(_globalErrorMutex);
 	return _globalError;
 }
 
diff --git a/aos/externals/WPILib/WPILib/ErrorBase.h b/aos/externals/WPILib/WPILib/ErrorBase.h
index f967562..9d032cb 100644
--- a/aos/externals/WPILib/WPILib/ErrorBase.h
+++ b/aos/externals/WPILib/WPILib/ErrorBase.h
@@ -10,59 +10,86 @@
 #include "Base.h"
 #include "ChipObject/NiRio.h"
 #include "Error.h"
-#include <semLib.h>
-#include <vxWorks.h>
 
-#define wpi_setErrnoErrorWithContext(context)   (this->SetErrnoError((context), __FILE__, __FUNCTION__, __LINE__))
-#define wpi_setErrnoError()   (wpi_setErrnoErrorWithContext(""))
-#define wpi_setImaqErrorWithContext(code, context)   (this->SetImaqError((code), (context), __FILE__, __FUNCTION__, __LINE__))
-#define wpi_setErrorWithContext(code, context)   (this->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+// Helper macros to fill in the context information for you. See the
+// documentation for the methods that they call for details.
+#define wpi_setErrnoErrorWithContext(context) \
+    (this->SetErrnoError((context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setErrnoError() \
+    (wpi_setErrnoErrorWithContext(""))
+#define wpi_setImaqErrorWithContext(code, context) \
+    (this->SetImaqError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setErrorWithContext(code, context) \
+        (this->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__))
 #define wpi_setError(code)   (wpi_setErrorWithContext(code, ""))
-#define wpi_setStaticErrorWithContext(object, code, context)   (object->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__))
-#define wpi_setStaticError(object, code)   (wpi_setStaticErrorWithContext(object, code, ""))
-#define wpi_setGlobalErrorWithContext(code, context)   (ErrorBase::SetGlobalError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setStaticErrorWithContext(object, code, context) \
+        (object->SetError((code), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setStaticError(object, code) \
+    (wpi_setStaticErrorWithContext(object, code, ""))
+#define wpi_setGlobalErrorWithContext(code, context) \
+        (ErrorBase::SetGlobalError((code), (context), \
+                                   __FILE__, __FUNCTION__, __LINE__))
 #define wpi_setGlobalError(code)   (wpi_setGlobalErrorWithContext(code, ""))
-#define wpi_setWPIErrorWithContext(error, context)   (this->SetWPIError((wpi_error_s_##error), (context), __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setWPIErrorWithContext(error, context) \
+        (this->SetWPIError((wpi_error_s_##error), (context), \
+                           __FILE__, __FUNCTION__, __LINE__))
 #define wpi_setWPIError(error)   (wpi_setWPIErrorWithContext(error, ""))
-#define wpi_setStaticWPIErrorWithContext(object, error, context)   (object->SetWPIError((wpi_error_s_##error), (context), __FILE__, __FUNCTION__, __LINE__))
-#define wpi_setStaticWPIError(object, error)   (wpi_setStaticWPIErrorWithContext(object, error, ""))
-#define wpi_setGlobalWPIErrorWithContext(error, context)   (ErrorBase::SetGlobalWPIError((wpi_error_s_##error), (context), __FILE__, __FUNCTION__, __LINE__))
-#define wpi_setGlobalWPIError(error)   (wpi_setGlobalWPIErrorWithContext(error, ""))
+#define wpi_setStaticWPIErrorWithContext(object, error, context) \
+        (object->SetWPIError((wpi_error_s_##error), (context), \
+                             __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setStaticWPIError(object, error) \
+    (wpi_setStaticWPIErrorWithContext(object, error, ""))
+#define wpi_setGlobalWPIErrorWithContext(error, context) \
+        (ErrorBase::SetGlobalWPIError((wpi_error_s_##error), (context), \
+                                      __FILE__, __FUNCTION__, __LINE__))
+#define wpi_setGlobalWPIError(error) \
+    (wpi_setGlobalWPIErrorWithContext(error, ""))
 
 /**
  * Base class for most objects.
  * ErrorBase is the base class for most objects since it holds the generated error
  * for that object. In addition, there is a single instance of a global error object
+ *
+ * BE AWARE: This does include a mutable instance variable! This means that even
+ * if you make an object const it's not really. However, all modification to
+ * that instance variable is protected by a semaphore, so it does not create any
+ * thread safety issues.
+ *
+ * All of the Set*Error methods will update the global error if there is nothing
+ * there already.
  */
 class ErrorBase
 {
-//TODO: Consider initializing instance variables and cleanup in destructor
 public:
+	ErrorBase();
 	virtual ~ErrorBase();
-	virtual Error& GetError();
-	virtual const Error& GetError() const;
-	virtual void SetErrnoError(const char *contextMessage,
+
+	Error& GetError() const;
+	void SetErrnoError(const char *contextMessage,
 		const char* filename, const char* function, UINT32 lineNumber) const;
-	virtual void SetImaqError(int success, const char *contextMessage,
+	void SetImaqError(int success, const char *contextMessage,
         const char* filename, const char* function, UINT32 lineNumber) const;
-	virtual void SetError(Error::Code code, const char *contextMessage,
+	void SetError(Error::Code code, const char *contextMessage,
 		const char* filename, const char* function, UINT32 lineNumber) const;
-	virtual void SetWPIError(const char *errorMessage, const char *contextMessage,
+	void SetWPIError(const char *errorMessage, const char *contextMessage,
 		const char* filename, const char* function, UINT32 lineNumber) const;
-	virtual void CloneError(ErrorBase *rhs) const;
-	virtual void ClearError() const;
-	virtual bool StatusIsFatal() const;
+	void CloneError(const ErrorBase *rhs) const;
+	void ClearError() const;
+	bool StatusIsFatal() const;
 	static void SetGlobalError(Error::Code code, const char *contextMessage,
 		const char* filename, const char* function, UINT32 lineNumber);
 	static void SetGlobalWPIError(const char *errorMessage, const char *contextMessage,
 		const char* filename, const char* function, UINT32 lineNumber);
-	static Error& GetGlobalError();
+	static const Error& GetGlobalError();
+
 protected:
+  // This mutable is safe because Error guarantees that all modifications are
+  // protected with an internal lock.
 	mutable Error m_error;
-	// TODO: Replace globalError with a global list of all errors.
-	static SEM_ID _globalErrorMutex;
+	// TODO: Replace globalError with a global list of all errors, but make sure
+  // that it's thread safe.
 	static Error _globalError;
-	ErrorBase();
+
 private:
 	DISALLOW_COPY_AND_ASSIGN(ErrorBase);
 };
diff --git a/aos/externals/WPILib/WPILib/Global.cpp b/aos/externals/WPILib/WPILib/Global.cpp
new file mode 100644
index 0000000..0d48129
--- /dev/null
+++ b/aos/externals/WPILib/WPILib/Global.cpp
@@ -0,0 +1,155 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include "Global.h"
+#include "Utility.h"
+
+Global *Global::instance;
+ReentrantSemaphore Global::instance_lock;
+
+Global *Global::GetInstance() {
+  Synchronized sync(instance_lock);
+  if (instance == NULL) {
+    instance = new Global();
+  }
+  return instance;
+}
+
+Global::Global() {
+	tRioStatusCode status = NiFpga_Status_Success;
+	global_.reset(tGlobal::create(&status));
+  wpi_setError(status);
+
+  AddToSingletonList();
+}
+
+Global::~Global() {
+  Synchronized sync(instance_lock);
+  instance = NULL;
+}
+
+/**
+ * Return the FPGA Version number.
+ * For now, expect this to be competition year.
+ * @return FPGA Version number.
+ */
+UINT16 Global::GetFPGAVersion()
+{
+	tRioStatusCode status = NiFpga_Status_Success;
+	UINT16 version = global_->readVersion(&status);
+	wpi_setError(status);
+	return version;
+}
+
+/**
+ * Return the FPGA Revision number.
+ * The format of the revision is 3 numbers.
+ * The 12 most significant bits are the Major Revision.
+ * the next 8 bits are the Minor Revision.
+ * The 12 least significant bits are the Build Number.
+ * @return FPGA Revision number.
+ */
+UINT32 Global::GetFPGARevision()
+{
+	tRioStatusCode status = NiFpga_Status_Success;
+	UINT32 revision = global_->readRevision(&status);
+	wpi_setError(status);
+	return revision;
+}
+
+/**
+ * Read the microsecond-resolution timer on the FPGA.
+ *
+ * @return The current time in microseconds according to the FPGA (since FPGA reset).
+ */
+UINT32 Global::GetFPGATime()
+{
+	tRioStatusCode status = NiFpga_Status_Success;
+	UINT32 time = global_->readLocalTime(&status);
+	wpi_setError(status);
+	return time;
+}
+
+// RT hardware access functions exported from ni_emb.out
+extern "C"
+{
+	INT32 UserSwitchInput(INT32 nSwitch);
+	INT32 LedInput(INT32 led);
+	INT32 LedOutput(INT32 led, INT32 value);
+}
+
+/**
+ * Read the value of the USER1 DIP switch on the cRIO.
+ */
+INT32 Global::GetRIOUserSwitch()
+{
+	INT32 switchValue = UserSwitchInput(0);
+	wpi_assert(switchValue >= 0);
+	return switchValue > 0;
+}
+
+/**
+ * Set the state of the USER1 status LED on the cRIO.
+ */
+void Global::SetRIOUserLED(UINT32 state)
+{
+	LedOutput(0, state > 0);
+}
+
+/**
+ * Get the current state of the USER1 status LED on the cRIO.
+ * @return The curent state of the USER1 LED.
+ */
+INT32 Global::GetRIOUserLED()
+{
+	return LedInput(0);
+}
+
+/**
+ * Toggle the state of the USER1 status LED on the cRIO.
+ * @return The new state of the USER1 LED.
+ */
+INT32 Global::ToggleRIOUserLED()
+{
+  Synchronized sync(led_toggle_lock_);
+	INT32 ledState = !GetRIOUserLED();
+	SetRIOUserLED(ledState);
+	return ledState;
+}
+
+/**
+ * Set the state of the FPGA status LED on the cRIO.
+ */
+void Global::SetRIO_FPGA_LED(UINT32 state)
+{
+	tRioStatusCode status = NiFpga_Status_Success;
+	global_->writeFPGA_LED(state, &status);
+	wpi_setError(status);
+}
+
+/**
+ * Get the current state of the FPGA status LED on the cRIO.
+ * @return The curent state of the FPGA LED.
+ */
+INT32 Global::GetRIO_FPGA_LED()
+{
+	tRioStatusCode status = NiFpga_Status_Success;
+	bool ledValue = global_->readFPGA_LED(&status);
+	wpi_setError(status);
+	return ledValue;
+}
+
+/**
+ * Toggle the state of the FPGA status LED on the cRIO.
+ * @return The new state of the FPGA LED.
+ */
+INT32 Global::ToggleRIO_FPGA_LED()
+{
+  Synchronized sync(led_toggle_lock_);
+	INT32 ledState = !GetRIO_FPGA_LED();
+	SetRIO_FPGA_LED(ledState);
+	return ledState;
+}
diff --git a/aos/externals/WPILib/WPILib/Global.h b/aos/externals/WPILib/WPILib/Global.h
new file mode 100644
index 0000000..4857e09
--- /dev/null
+++ b/aos/externals/WPILib/WPILib/Global.h
@@ -0,0 +1,42 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include <memory>
+
+#include "SensorBase.h"
+#include "Synchronized.h"
+#include "ChipObject.h"
+
+#ifndef WPILIB_GLOBAL_H_
+#define WPILIB_GLOBAL_H_
+
+class Global : public SensorBase {
+ public:
+  static Global *GetInstance();
+
+  UINT16 GetFPGAVersion();
+  UINT32 GetFPGARevision();
+  UINT32 GetFPGATime();
+  INT32 GetRIOUserSwitch();
+  void SetRIOUserLED(UINT32 state);
+  INT32 GetRIOUserLED();
+  INT32 ToggleRIOUserLED();
+  void SetRIO_FPGA_LED(UINT32 state);
+  INT32 GetRIO_FPGA_LED();
+  INT32 ToggleRIO_FPGA_LED();
+
+ private:
+  Global();
+  ~Global();
+
+  static Global *instance;
+  static ReentrantSemaphore instance_lock;
+
+  ::std::auto_ptr<tGlobal> global_;
+  ReentrantSemaphore led_toggle_lock_;
+};
+
+#endif  // WPILIB_GLOBAL_H_
diff --git a/aos/externals/WPILib/WPILib/IterativeRobot.cpp b/aos/externals/WPILib/WPILib/IterativeRobot.cpp
index 96e9b71..579ea2b 100644
--- a/aos/externals/WPILib/WPILib/IterativeRobot.cpp
+++ b/aos/externals/WPILib/WPILib/IterativeRobot.cpp
@@ -61,7 +61,7 @@
 
 /**
  * Get the period for the periodic functions.
- * Returns 0.0 if configured to syncronize with DS control data packets.
+ * Returns 0.0 if configured to synchronize with DS control data packets.
  * @return Period of the periodic function calls
  */
 double IterativeRobot::GetPeriod()
@@ -87,8 +87,7 @@
  * 
  * This specific StartCompetition() implements "main loop" behavior like that of the FRC
  * control system in 2008 and earlier, with a primary (slow) loop that is
- * called periodically, and a "fast loop" (a.k.a. "spin loop") that is 
- * called as fast as possible with no delay between calls. 
+ * called periodically.
  */
 void IterativeRobot::StartCompetition()
 {
diff --git a/aos/externals/WPILib/WPILib/LiveWindow/LiveWindow.h b/aos/externals/WPILib/WPILib/LiveWindow/LiveWindow.h
index 7237afa..b3e620e 100644
--- a/aos/externals/WPILib/WPILib/LiveWindow/LiveWindow.h
+++ b/aos/externals/WPILib/WPILib/LiveWindow/LiveWindow.h
@@ -24,6 +24,10 @@
 		this->subsystem = subsystem;
 		this->name = name;
 		this->isSensor = isSensor;
+#else
+    (void)subsystem;
+    (void)name;
+    (void)isSensor;
 #endif
 	}
 };
diff --git a/aos/externals/WPILib/WPILib/Module.cpp b/aos/externals/WPILib/WPILib/Module.cpp
index 99e26ea..2d01ea5 100644
--- a/aos/externals/WPILib/WPILib/Module.cpp
+++ b/aos/externals/WPILib/WPILib/Module.cpp
@@ -8,6 +8,9 @@
 #include "AnalogModule.h"
 #include "DigitalModule.h"
 //#include "SolenoidModule.h"
+#include "Utility.h"
+
+ReentrantSemaphore Module::m_semaphore;
 
 Module* Module::m_modules[kMaxModules] = {NULL};
 
@@ -21,6 +24,7 @@
 	: m_moduleType (type)
 	, m_moduleNumber (number)
 {
+  Synchronized sync(m_semaphore);
 	m_modules[ToIndex(type, number)] = this;
 }
 
@@ -29,6 +33,7 @@
  */
 Module::~Module()
 {
+  m_modules[ToIndex(m_moduleType, m_moduleNumber)] = NULL;
 }
 
 /**
@@ -39,6 +44,7 @@
  */
 Module* Module::GetModule(nLoadOut::tModuleType type, UINT8 number)
 {
+  Synchronized sync(m_semaphore);
 	if (m_modules[ToIndex(type, number)] == NULL)
 	{
 		switch(type)
@@ -70,7 +76,20 @@
  */
 UINT8 Module::ToIndex(nLoadOut::tModuleType type, UINT8 number)
 {
-	if (number == 0 || number > kMaxModuleNumber) return 0;
-	if (type < nLoadOut::kModuleType_Analog || type > nLoadOut::kModuleType_Solenoid) return 0;
+	if (number == 0 || number > kMaxModuleNumber) {
+    char buf[64];
+    snprintf(buf, sizeof(buf), "Trying to get index for invalid module %d",
+             static_cast<int>(number));
+    wpi_assertWithMessage(false, buf);
+    return 0;
+  }
+	if (type < nLoadOut::kModuleType_Analog ||
+      type > nLoadOut::kModuleType_Solenoid) {
+    char buf[64];
+    snprintf(buf, sizeof(buf), "Trying to get index for invalid module type %d",
+             static_cast<int>(type));
+    wpi_assertWithMessage(false, buf);
+    return 0;
+  }
 	return (type * kMaxModuleNumber) + (number - 1);
 }
diff --git a/aos/externals/WPILib/WPILib/Module.h b/aos/externals/WPILib/WPILib/Module.h
index 1c9f976..45b10ff 100644
--- a/aos/externals/WPILib/WPILib/Module.h
+++ b/aos/externals/WPILib/WPILib/Module.h
@@ -9,6 +9,7 @@
 
 #include "SensorBase.h"
 #include "NetworkCommunication/LoadOut.h"
+#include "Synchronized.h"
 
 #define kMaxModules	(nLoadOut::kModuleType_Solenoid * kMaxModuleNumber + (kMaxModuleNumber - 1))
 
@@ -20,7 +21,7 @@
 	static Module *GetModule(nLoadOut::tModuleType type, UINT8 number);
 
 protected:
-	explicit Module(nLoadOut::tModuleType type, UINT8 number);
+	Module(nLoadOut::tModuleType type, UINT8 number);
 	virtual ~Module();
 
 	nLoadOut::tModuleType m_moduleType; ///< The type of module represented.
@@ -29,6 +30,7 @@
 private:
 	static UINT8 ToIndex(nLoadOut::tModuleType type, UINT8 number);
 	static Module* m_modules[kMaxModules];
+  static ReentrantSemaphore m_semaphore;
 };
 
 #endif
diff --git a/aos/externals/WPILib/WPILib/MotorSafety.h b/aos/externals/WPILib/WPILib/MotorSafety.h
index 15481d8..a13ac38 100644
--- a/aos/externals/WPILib/WPILib/MotorSafety.h
+++ b/aos/externals/WPILib/WPILib/MotorSafety.h
@@ -16,6 +16,7 @@
 	virtual void StopMotor() = 0;
 	virtual void SetSafetyEnabled(bool enabled) = 0;
 	virtual bool IsSafetyEnabled() = 0;
+  // May write to the first 64 bytes of desc.
 	virtual void GetDescription(char *desc) = 0;
 };
 
diff --git a/aos/externals/WPILib/WPILib/PWM.cpp b/aos/externals/WPILib/WPILib/PWM.cpp
index 05bf16d..7ae5370 100644
--- a/aos/externals/WPILib/WPILib/PWM.cpp
+++ b/aos/externals/WPILib/WPILib/PWM.cpp
@@ -42,9 +42,9 @@
 	}
 
 	snprintf(buf, 64, "PWM %d (Module: %d)", channel, moduleNumber);
-	if (allocated->Allocate((moduleNumber - 1) * kPwmChannels + channel - 1, buf) == ~0ul)
+	if (allocated->Allocate((moduleNumber - 1) * kPwmChannels + channel - 1,
+                          buf, this) == ~0ul)
 	{
-		CloneError(allocated);
 		return;
 	}
 	m_channel = channel;
@@ -92,7 +92,8 @@
 	if (m_module)
 	{
 		m_module->SetPWM(m_channel, kPwmDisabled);
-		allocated->Free((m_module->GetNumber() - 1) * kPwmChannels + m_channel - 1);
+		allocated->Free((m_module->GetNumber() - 1) * kPwmChannels + m_channel - 1,
+                    this);
 	}
 }
 
diff --git a/aos/externals/WPILib/WPILib/RWLock.cpp b/aos/externals/WPILib/WPILib/RWLock.cpp
new file mode 100644
index 0000000..9918af0
--- /dev/null
+++ b/aos/externals/WPILib/WPILib/RWLock.cpp
@@ -0,0 +1,202 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#include <taskLib.h>
+#include <intLib.h>
+#include <assert.h>
+
+#include "RWLock.h"
+
+// A wrapper for assert that allows it to be easily turned off just in this
+// file. That configuration is recommended for normal use because it means less
+// code that gets executed with the scheduler locked.
+#if 1
+#define rwlock_assert(expression) assert(expression)
+// A macro to easily assert that some expression (possibly with side effects)
+// is 0.
+#define rwlock_assert_success(expression) do { \
+  int ret = (expression); \
+  assert(ret == 0); \
+} while (false)
+#else
+#define rwlock_assert(expression) ((void)0)
+#define rwlock_assert_success(expression) ((void)(expression))
+#endif
+
+/**
+ * Class that locks the scheduler and then unlocks it in the destructor.
+ */
+class TaskSchedulerLocker {
+ public:
+  TaskSchedulerLocker() {
+    rwlock_assert_success(taskLock());
+  }
+  ~TaskSchedulerLocker() {
+    rwlock_assert_success(taskUnlock());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TaskSchedulerLocker);
+};
+
+RWLock::Locker::Locker(RWLock *lock, bool write)
+  : lock_(lock), num_(lock_->Lock(write)) {
+}
+
+RWLock::Locker::Locker(const Locker &other)
+  : lock_(other.lock_), num_(lock_->AddLock()) {
+}
+
+RWLock::Locker::~Locker() {
+  lock_->Unlock(num_);
+}
+
+// RWLock is implemented by just locking the scheduler while doing anything
+// because that is the only way under vxworks to do much of anything atomically.
+
+RWLock::RWLock()
+  : number_of_write_locks_(0),
+    number_of_writers_pending_(0),
+    number_of_readers_(0),
+    reader_tasks_(),
+    read_ready_(semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)),
+    write_ready_(semBCreate(SEM_Q_PRIORITY, SEM_EMPTY)) {
+  rwlock_assert(read_ready_ != NULL);
+  rwlock_assert(write_ready_ != NULL);
+}
+
+RWLock::~RWLock() {
+  // Make sure that nobody else currently has a lock or will ever be able to.
+  Lock(true);
+
+  rwlock_assert_success(semDelete(read_ready_));
+  rwlock_assert_success(semDelete(write_ready_));
+}
+
+int RWLock::Lock(bool write) {
+  assert(!intContext());
+
+  int current_task = taskIdSelf();
+  // It's safe to do this check up here (outside of locking the scheduler)
+  // because we only care whether the current task is in there or not and that
+  // can't be changed because it's the task doing the checking.
+  bool current_task_holds_already = TaskOwns(current_task);
+
+  TaskSchedulerLocker scheduler_locker;
+
+  // We can't be reading and writing at the same time.
+  rwlock_assert(!((number_of_write_locks_ > 0) && (number_of_readers_ > 0)));
+
+  if (write) {
+    assert(!current_task_holds_already);
+    // If somebody else already has it locked.
+    // Don't have to worry about another task getting scheduled after
+    // write_ready_ gets given because nobody else (except another writer, which
+    // would just block on it) will do anything while there are pending
+    // writer(s).
+    if ((number_of_readers_ > 0) || (number_of_write_locks_ > 0)) {
+      ++number_of_writers_pending_;
+      // Wait for it to be our turn.
+      rwlock_assert_success(semTake(write_ready_, WAIT_FOREVER));
+      --number_of_writers_pending_;
+    } else {
+      rwlock_assert(number_of_writers_pending_ == 0);
+    }
+    rwlock_assert((number_of_write_locks_ == 0) && (number_of_readers_ == 0));
+    number_of_write_locks_ = 1;
+    return 0;
+  } else {  // read
+    // While there are one or more writers active or waiting.
+    // Has to be a loop in case a writer gets scheduled between the time
+    // read_ready_ gets flushed and we run.
+    while ((number_of_write_locks_ > 0) || (number_of_writers_pending_ > 0)) {
+      // Wait for the writer(s) to finish.
+      rwlock_assert_success(semTake(read_ready_, WAIT_FOREVER));
+    }
+
+    int num = number_of_readers_;
+    number_of_readers_ = num + 1;
+    assert(num < kMaxReaders);
+    rwlock_assert(reader_tasks_[num] == 0);
+    reader_tasks_[num] = current_task;
+    rwlock_assert((number_of_write_locks_ == 0) && (number_of_readers_ > 0));
+    return num;
+  }
+}
+
+void RWLock::Unlock(int num) {
+  assert(!intContext());
+  TaskSchedulerLocker scheduler_locker;
+
+  // We have to be reading or writing right now, but not both.
+  rwlock_assert((number_of_write_locks_ > 0) != (number_of_readers_ > 0));
+
+  if (number_of_write_locks_ > 0) {  // we're currently writing
+    rwlock_assert(num == 0);
+    --number_of_write_locks_;
+    rwlock_assert((number_of_write_locks_ >= 0) &&
+                  (number_of_writers_pending_ >= 0));
+    // If we were the last one.
+    if (number_of_write_locks_ == 0) {
+      // If there are no other tasks waiting to write (because otherwise they
+      // need to get priority over any readers).
+      if (number_of_writers_pending_ == 0) {
+        // Wake up any waiting readers.
+        rwlock_assert_success(semFlush(read_ready_));
+      } else {
+        // Wake up a waiting writer.
+        // Not a problem if somebody else already did this before the waiting
+        // writer got a chance to take it because it'll do nothing and return
+        // success.
+        rwlock_assert_success(semGive(write_ready_));
+      }
+    }
+  } else {  // we're curently reading
+    rwlock_assert(reader_tasks_[num] == taskIdSelf());
+    reader_tasks_[num] = 0;
+    --number_of_readers_;
+    rwlock_assert(number_of_readers_ >= 0 &&
+                  (number_of_writers_pending_ >= 0));
+    // If we were the last one.
+    if (number_of_readers_ == 0) {
+      // If there are any writers waiting for a chance to go.
+      if (number_of_writers_pending_ > 0) {
+        // Wake a waiting writer.
+        // Not a problem if somebody else already did this before the waiting
+        // writer got a chance to take it because it'll still return success.
+        rwlock_assert_success(semGive(write_ready_));
+      }
+    }
+  }
+}
+
+int RWLock::AddLock() {
+  assert(!intContext());
+  // TODO: Replace this with just atomically incrementing the right number once
+  // we start using a GCC new enough to have the nice atomic builtins.
+  // That will be safe because whether we're currently reading or writing can't
+  // change in the middle of this.
+  TaskSchedulerLocker scheduler_locker;
+
+  // We have to be reading or writing right now, but not both.
+  rwlock_assert((number_of_write_locks_ > 0) != (number_of_readers_ > 0));
+
+  if (number_of_write_locks_ > 0) {  // we're currently writing
+    ++number_of_write_locks_;
+    return 0;
+  } else {  // we're currently reading
+    return number_of_readers_++;
+  }
+}
+
+bool RWLock::TaskOwns(int task_id) {
+  for (size_t i = 0;
+       i < sizeof(reader_tasks_) / sizeof(reader_tasks_[0]);
+       ++i) {
+    if (reader_tasks_[i] == task_id) return true;
+  }
+  return false;
+}
diff --git a/aos/externals/WPILib/WPILib/RWLock.h b/aos/externals/WPILib/WPILib/RWLock.h
new file mode 100644
index 0000000..13d7b50
--- /dev/null
+++ b/aos/externals/WPILib/WPILib/RWLock.h
@@ -0,0 +1,125 @@
+/*----------------------------------------------------------------------------*/
+/* Copyright (c) FIRST 2008. All Rights Reserved.                             */
+/* Open Source Software - may be modified and shared by FRC teams. The code   */
+/* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib.  */
+/*----------------------------------------------------------------------------*/
+
+#ifndef WPILIB_DATA_LOCK_H_
+#define WPILIB_DATA_LOCK_H_
+
+#include <semLib.h>
+
+#include "Base.h"
+
+/**
+ * Represents a read/write lock on using some shared data so that it will not
+ * be modified by any other tasks while code is using it.
+ *
+ * See <http://en.wikipedia.org/wiki/Readers-writer_lock> for an overview of how
+ * this can be used.
+ *
+ * In this implementation, if there are any writers pending, then any new
+ * attempts to acquire read locks will wait until all writers are done unless a
+ * read lock is already held by that same task.
+ */
+class RWLock {
+ public:
+  /**
+   * Represents an actual lock on the shared data. The destructor will free it.
+   *
+   * Intended to be used as an automatic (or local) variable so that the
+   * compiler will ensure that the destructor gets called no matter how the
+   * scope is exited.
+   *
+   * While it is possible to use new/delete to dynamically allocate an instance,
+   * the constructor and destructor still MUST still be called from the same
+   * task.
+   *
+   * Has a copy constructor which allows "copying" the lock that is held. Does
+   * not have an assignment operator because assigning a lock doesn't make much
+   * sense.
+   */
+  class Locker {
+   public:
+    /**
+     * @param write Whether to create a writer lock (creates a reader lock
+     * otherwise).
+     */
+    Locker(RWLock *lock, bool write);
+
+    /**
+     * Creates another lock of the same type. They can both be released
+     * (destructed) independently.
+     * NOTE: This does allow creating multiple write locks that are held at the
+     * same time.
+     */
+    Locker(const Locker &other);
+
+    /**
+     * Unlocks the lock.
+     */
+    ~Locker();
+
+   private:
+    RWLock *const lock_;
+    const int num_;
+
+    void operator=(const Locker &);
+  };
+
+  /**
+   * The maximum number of read locks that can be held at the same time.
+   */
+  static const int kMaxReaders = 64;
+
+  RWLock();
+  /**
+   * Waits until there are no more read or write locks held.
+   */
+  ~RWLock();
+
+ private:
+  // The number of write locks that are currently held.
+  int number_of_write_locks_;
+  // How many tasks are currently waiting to get a write lock.
+  // Each count in here corresponds to a task that is blocked on write_ready_.
+  int number_of_writers_pending_;
+
+  // How many read locks are currently held.
+  int number_of_readers_;
+
+  // The task ID of the task holding each read lock.
+  int reader_tasks_[kMaxReaders];
+
+  // Always locked. Gets semFlushed when readers are allowed to take the lock
+  // (after all writers are done).
+  SEM_ID read_ready_;
+  // Locked almost all of the time. Pending writers (who have to update
+  // number_of_writers_pending_) block locking this and it gets unlocked when it
+  // is time for one of them to go.
+  SEM_ID write_ready_;
+
+  // Acquires the appropriate kind of lock.
+  // Returns a value that must be passed to the corresponding Unlock call.
+  int Lock(bool write);
+  // Unlocks 1 lock.
+  // Does not need to know whether it is read or write because only one type of
+  // lock can be held at a time.
+  // num must be the return value from the corresponding Lock/AddLock call.
+  void Unlock(int num);
+  // Increments the lock count by 1.
+  // There must be at least 1 lock held during the execution of this method.
+  // Use the regular Unlock() to unlock a lock acquired this way.
+  // This is not the same as Lock(current_type) because this is the only way to
+  // acquire multiple write locks at the same time.
+  // Returns a value that must be passed to the corresponding Unlock call.
+  int AddLock();
+  // Checks whether task_id is in reader_tasks_.
+  bool TaskOwns(int task_id);
+
+  friend class Locker;
+
+  DISALLOW_COPY_AND_ASSIGN(RWLock);
+};
+
+#endif  // WPILIB_DATA_LOCK_H_
diff --git a/aos/externals/WPILib/WPILib/Relay.cpp b/aos/externals/WPILib/WPILib/Relay.cpp
index dd59d52..9fb3a2d 100644
--- a/aos/externals/WPILib/WPILib/Relay.cpp
+++ b/aos/externals/WPILib/WPILib/Relay.cpp
@@ -43,9 +43,9 @@
 	if (m_direction == kBothDirections || m_direction == kForwardOnly)
 	{
 		snprintf(buf, 64, "Forward Relay %d (Module: %d)", m_channel, moduleNumber);
-		if (relayChannels->Allocate(((moduleNumber - 1) * kRelayChannels + m_channel - 1) * 2, buf) == ~0ul)
+		if (relayChannels->Allocate(((moduleNumber - 1) * kRelayChannels +
+                                 m_channel - 1) * 2, buf, this) == ~0ul)
 		{
-			CloneError(relayChannels);
 			return;
 		}
 
@@ -54,9 +54,9 @@
 	if (m_direction == kBothDirections || m_direction == kReverseOnly)
 	{
 		snprintf(buf, 64, "Reverse Relay %d (Module: %d)", m_channel, moduleNumber);
-		if (relayChannels->Allocate(((moduleNumber - 1) * kRelayChannels + m_channel - 1) * 2 + 1, buf) == ~0ul)
+		if (relayChannels->Allocate(((moduleNumber - 1) * kRelayChannels
+                                 + m_channel - 1) * 2 + 1, buf, this) == ~0ul)
 		{
-			CloneError(relayChannels);
 			return;
 		}
 
@@ -105,11 +105,13 @@
 
 	if (m_direction == kBothDirections || m_direction == kForwardOnly)
 	{
-		relayChannels->Free(((m_module->GetNumber() - 1) * kRelayChannels + m_channel - 1) * 2);
+		relayChannels->Free(((m_module->GetNumber() - 1) *
+                         kRelayChannels + m_channel - 1) * 2, this);
 	}
 	if (m_direction == kBothDirections || m_direction == kReverseOnly)
 	{
-		relayChannels->Free(((m_module->GetNumber() - 1) * kRelayChannels + m_channel - 1) * 2 + 1);
+		relayChannels->Free(((m_module->GetNumber() - 1) *
+                         kRelayChannels + m_channel - 1) * 2 + 1, this);
 	}
 }
 
diff --git a/aos/externals/WPILib/WPILib/Resource.cpp b/aos/externals/WPILib/WPILib/Resource.cpp
index ec35eb3..ef7d15d 100644
--- a/aos/externals/WPILib/WPILib/Resource.cpp
+++ b/aos/externals/WPILib/WPILib/Resource.cpp
@@ -6,7 +6,6 @@
 
 #include "Resource.h"
 #include "WPIErrors.h"
-#include "ErrorBase.h"
 
 ReentrantSemaphore Resource::m_createLock;
 
@@ -28,6 +27,7 @@
 
 /**
  * Factory method to create a Resource allocation-tracker *if* needed.
+ * Handles the necessary synchronization internally.
  *
  * @param r -- address of the caller's Resource pointer. If *r == NULL, this
  *    will construct a Resource and make *r point to it. If *r != NULL, i.e.
@@ -59,7 +59,7 @@
  * When a resource is requested, mark it allocated. In this case, a free resource value
  * within the range is located and returned after it is marked allocated.
  */
-UINT32 Resource::Allocate(const char *resourceDesc)
+UINT32 Resource::Allocate(const char *resourceDesc, const ErrorBase *error)
 {
 	Synchronized sync(m_allocateLock);
 	for (UINT32 i=0; i < m_size; i++)
@@ -70,7 +70,7 @@
 			return i;
 		}
 	}
-	wpi_setWPIErrorWithContext(NoAvailableResources, resourceDesc);
+	wpi_setStaticWPIErrorWithContext(error, NoAvailableResources, resourceDesc);
 	return ~0ul;
 }
 
@@ -79,17 +79,18 @@
  * The user requests a specific resource value, i.e. channel number and it is verified
  * unallocated, then returned.
  */
-UINT32 Resource::Allocate(UINT32 index, const char *resourceDesc)
+UINT32 Resource::Allocate(UINT32 index, const char *resourceDesc,
+                          const ErrorBase *error)
 {
 	Synchronized sync(m_allocateLock);
 	if (index >= m_size)
 	{
-		wpi_setWPIErrorWithContext(ChannelIndexOutOfRange, resourceDesc);
+		wpi_setStaticWPIErrorWithContext(error, ChannelIndexOutOfRange, resourceDesc);
 		return ~0ul;
 	}
 	if ( m_isAllocated[index] )
 	{
-		wpi_setWPIErrorWithContext(ResourceAlreadyAllocated, resourceDesc);
+		wpi_setStaticWPIErrorWithContext(error, ResourceAlreadyAllocated, resourceDesc);
 		return ~0ul;
 	}
 	m_isAllocated[index] = true;
@@ -102,18 +103,18 @@
  * After a resource is no longer needed, for example a destructor is called for a channel assignment
  * class, Free will release the resource value so it can be reused somewhere else in the program.
  */
-void Resource::Free(UINT32 index)
+void Resource::Free(UINT32 index, const ErrorBase *error)
 {
 	Synchronized sync(m_allocateLock);
 	if (index == ~0ul) return;
 	if (index >= m_size)
 	{
-		wpi_setWPIError(NotAllocated);
+		wpi_setStaticWPIError(error, NotAllocated);
 		return;
 	}
 	if (!m_isAllocated[index])
 	{
-		wpi_setWPIError(NotAllocated);
+		wpi_setStaticWPIError(error, NotAllocated);
 		return;
 	}
 	m_isAllocated[index] = false;
diff --git a/aos/externals/WPILib/WPILib/Resource.h b/aos/externals/WPILib/WPILib/Resource.h
index dbe1936..11faaec 100644
--- a/aos/externals/WPILib/WPILib/Resource.h
+++ b/aos/externals/WPILib/WPILib/Resource.h
@@ -19,15 +19,18 @@
  * The Resource class does not allocate the hardware channels or other
  * resources; it just tracks which indices were marked in use by
  * Allocate and not yet freed by Free.
+ *
+ * Several methods require an ErrorBase* so that they can report any errors.
  */
-class Resource : public ErrorBase
+class Resource
 {
 public:
 	virtual ~Resource();
 	static void CreateResourceObject(Resource **r, UINT32 elements);
-	UINT32 Allocate(const char *resourceDesc);
-	UINT32 Allocate(UINT32 index, const char *resourceDesc);
-	void Free(UINT32 index);
+	UINT32 Allocate(const char *resourceDesc, const ErrorBase *error);
+	UINT32 Allocate(UINT32 index, const char *resourceDesc,
+                  const ErrorBase *error);
+	void Free(UINT32 index, const ErrorBase *error);
 
 private:
 	explicit Resource(UINT32 size);
diff --git a/aos/externals/WPILib/WPILib/RobotBase.cpp b/aos/externals/WPILib/WPILib/RobotBase.cpp
index 0bebf09..17c7682 100644
--- a/aos/externals/WPILib/WPILib/RobotBase.cpp
+++ b/aos/externals/WPILib/WPILib/RobotBase.cpp
@@ -19,6 +19,8 @@
 
 void RobotBase::setInstance(RobotBase* robot)
 {
+  // No point in synchronization here because it's private and it only gets
+  // called from robotTask.
 	wpi_assert(m_instance == NULL);
 	m_instance = robot;
 }
@@ -30,8 +32,9 @@
 
 /**
  * Constructor for a generic robot program.
- * User code should be placed in the constuctor that runs before the Autonomous or Operator
- * Control period starts. The constructor will run to completion before Autonomous is entered.
+ * User code that should run before the Autonomous or Operator Control period
+ * starts should be placed in the subclass constructor.
+ * The constructor must finish before Autonomous can be entered.
  * 
  * This must be used to ensure that the communications code starts. In the future it would be
  * nice to put this code into it's own task that loads on boot so ensure that it runs.
@@ -45,7 +48,7 @@
 
 /**
  * Free the resources for a RobotBase class.
- * This includes deleting all classes that might have been allocated as Singletons to they
+ * This includes deleting all classes that might have been allocated as Singletons so they
  * would never be deleted except here.
  */
 RobotBase::~RobotBase()
@@ -95,7 +98,7 @@
 }
 
 /**
- * Determine if the robot is currently in Autnomous mode.
+ * Determine if the robot is currently in Autonomous mode.
  * @return True if the robot is currently operating Autonomously as determined by the field controls.
  */
 bool RobotBase::IsAutonomous()
@@ -135,18 +138,21 @@
  */
 void RobotBase::robotTask(FUNCPTR factory, Task *task)
 {
-	RobotBase::setInstance((RobotBase*)factory());
-	RobotBase::getInstance().m_task = task;
-	RobotBase::getInstance().StartCompetition();
+  RobotBase *instance = (RobotBase*)factory();
+  instance->m_task = task;
+  RobotBase::setInstance(instance);
+  instance->StartCompetition();
 }
 
 /**
  * 
  * Start the robot code.
- * This function starts the robot code running by spawning a task. Currently tasks seemed to be
- * started by LVRT without setting the VX_FP_TASK flag so floating point context is not saved on
- * interrupts. Therefore the program experiences hard to debug and unpredictable results. So the
- * LVRT code starts this function, and it, in turn, starts the actual user program.
+ * This function starts the robot code running by spawning a task. Currently
+ * tasks seem to be started by LVRT without setting the VX_FP_TASK flag which
+ * means that the floating point registers are not saved on interrupts and task
+ * switches. That causes the program to experience hard to debug and
+ * unpredictable results, so the LVRT code starts this function, so that it, in
+ * turn, can start the actual user program.
  */
 void RobotBase::startRobotTask(FUNCPTR factory)
 {
@@ -199,8 +205,7 @@
 /**
  * This class exists for the sole purpose of getting its destructor called when the module unloads.
  * Before the module is done unloading, we need to delete the RobotBase derived singleton.  This should delete
- * the other remaining singletons that were registered.  This should also stop all tasks that are using
- * the Task class.
+ * the other remaining singletons that were registered.
  */
 class RobotDeleter
 {
diff --git a/aos/externals/WPILib/WPILib/RobotBase.h b/aos/externals/WPILib/WPILib/RobotBase.h
index ac15250..45c24dd 100644
--- a/aos/externals/WPILib/WPILib/RobotBase.h
+++ b/aos/externals/WPILib/WPILib/RobotBase.h
@@ -13,6 +13,11 @@
 
 class DriverStation;
 
+/**
+ * This macro will set up the given class (which must be a (direct or indirect)
+ * RobotBase subclass) so that when the user code is loaded, it will be
+ * instantiated and StartCompetition() will be called on the instance.
+ */
 #define START_ROBOT_CLASS(_ClassName_) \
 	RobotBase *FRC_userClassFactory() \
 	{ \
@@ -28,17 +33,14 @@
 
 /**
  * Implement a Robot Program framework.
- * The RobotBase class is intended to be subclassed by a user creating a robot program.
- * Overridden Autonomous() and OperatorControl() methods are called at the appropriate time
- * as the match proceeds. In the current implementation, the Autonomous code will run to
- * completion before the OperatorControl code could start. In the future the Autonomous code
- * might be spawned as a task, then killed at the end of the Autonomous period.
+ * The RobotBase class is intended to be subclassed by a user creating a robot
+ * program, possibly indirectly through one of the subclasses included in this
+ * library.
  */
 class RobotBase {
 	friend class RobotDeleter;
 public:
 	static RobotBase &getInstance();
-	static void setInstance(RobotBase* robot);
 
 	bool IsEnabled();
 	bool IsDisabled();
@@ -49,13 +51,15 @@
 	bool IsNewDataAvailable();
 	Watchdog &GetWatchdog();
 	static void startRobotTask(FUNCPTR factory);
-	static void robotTask(FUNCPTR factory, Task *task);
 
 protected:
 	virtual ~RobotBase();
 	virtual void StartCompetition() = 0;
 	RobotBase();
 
+	static void setInstance(RobotBase* robot);
+	static void robotTask(FUNCPTR factory, Task *task);
+
 	Task *m_task;
 	Watchdog m_watchdog;
 	DriverStation *m_ds;
diff --git a/aos/externals/WPILib/WPILib/RobotDrive.cpp b/aos/externals/WPILib/WPILib/RobotDrive.cpp
index 14e28f5..1d538c5 100644
--- a/aos/externals/WPILib/WPILib/RobotDrive.cpp
+++ b/aos/externals/WPILib/WPILib/RobotDrive.cpp
@@ -725,7 +725,7 @@
 
 void RobotDrive::GetDescription(char *desc)
 {
-	sprintf(desc, "RobotDrive");
+	snprintf(desc, 64, "RobotDrive");
 }
 
 void RobotDrive::StopMotor()
diff --git a/aos/externals/WPILib/WPILib/SafePWM.cpp b/aos/externals/WPILib/WPILib/SafePWM.cpp
index 484fbe6..989d782 100644
--- a/aos/externals/WPILib/WPILib/SafePWM.cpp
+++ b/aos/externals/WPILib/WPILib/SafePWM.cpp
@@ -100,7 +100,7 @@
 
 void SafePWM::GetDescription(char *desc)
 {
-	sprintf(desc, "PWM %d on module %d", GetChannel(), GetModuleNumber());
+	snprintf(desc, 64, "PWM %d on module %d", GetChannel(), GetModuleNumber());
 }
 
 /**
diff --git a/aos/externals/WPILib/WPILib/SensorBase.cpp b/aos/externals/WPILib/WPILib/SensorBase.cpp
index a68d260..5574a35 100644
--- a/aos/externals/WPILib/WPILib/SensorBase.cpp
+++ b/aos/externals/WPILib/WPILib/SensorBase.cpp
@@ -7,7 +7,6 @@
 #include "SensorBase.h"
 
 #include "NetworkCommunication/LoadOut.h"
-#include "WPIErrors.h"
 
 const UINT32 SensorBase::kSystemClockTicksPerMicrosecond;
 const UINT32 SensorBase::kDigitalChannels;
@@ -18,11 +17,11 @@
 const UINT32 SensorBase::kSolenoidModules;
 const UINT32 SensorBase::kPwmChannels;
 const UINT32 SensorBase::kRelayChannels;
-const UINT32 SensorBase::kChassisSlots;
 SensorBase *SensorBase::m_singletonList = NULL;
+ReentrantSemaphore SensorBase::m_singletonListSemaphore;
 
 /**
- * Creates an instance of the sensor base and gets an FPGA handle
+ * Creates an instance of SensorBase.
  */
 SensorBase::SensorBase()
 {
@@ -36,27 +35,31 @@
 }
 
 /**
- * Add sensor to the singleton list.
- * Add this sensor to the list of singletons that need to be deleted when
- * the robot program exits. Each of the sensors on this list are singletons,
- * that is they aren't allocated directly with new, but instead are allocated
- * by the static GetInstance method. As a result, they are never deleted when
- * the program exits. Consequently these sensors may still be holding onto
- * resources and need to have their destructors called at the end of the program.
+ * @brief Add sensor to the singleton list.
+ * Add this object to the list of singletons that need to be deleted when
+ * the robot program exits. Each of the objects on this list are singletons,
+ * that is they aren't allocated directly by user code, but instead are
+ * allocated by (for example) a static GetInstance method. Because of this, they
+ * need some way to be freed when the module is unloaded so that they can free
+ * any resources that they are holding on to.
+ * @see #DeleteSingletons()
  */
 void SensorBase::AddToSingletonList()
 {
+  Synchronized sync(m_singletonListSemaphore);
 	m_nextSingleton = m_singletonList;
 	m_singletonList = this;
 }
 
 /**
- * Delete all the singleton classes on the list.
- * All the classes that were allocated as singletons need to be deleted so
+ * @brief Delete all the singleton objects on the list.
+ * All the objects that were allocated as singletons need to be deleted so
  * their resources can be freed.
+ * @see #AddToSingletonList()
  */
 void SensorBase::DeleteSingletons()
 {
+  Synchronized sync(m_singletonListSemaphore);
 	for (SensorBase *next = m_singletonList; next != NULL;)
 	{
 		SensorBase *tmp = next;
diff --git a/aos/externals/WPILib/WPILib/SensorBase.h b/aos/externals/WPILib/WPILib/SensorBase.h
index 1b149b1..3f12360 100644
--- a/aos/externals/WPILib/WPILib/SensorBase.h
+++ b/aos/externals/WPILib/WPILib/SensorBase.h
@@ -7,20 +7,19 @@
 #ifndef SENSORBASE_H_
 #define SENSORBASE_H_
 
-#include "ChipObject/NiRio.h"
 #include "ErrorBase.h"
 #include <stdio.h>
 #include "Base.h"
+#include "Synchronized.h"
 
 /**
  * Base class for all sensors.
  * Stores most recent status information as well as containing utility functions for checking
- * channels and error processing.
+ * channels.
  */
 class SensorBase: public ErrorBase {
 public:
 	SensorBase();
-	virtual ~SensorBase();
 	static void DeleteSingletons();
 	static UINT32 GetDefaultAnalogModule() { return 1; }
 	static UINT32 GetDefaultDigitalModule() { return 1; }
@@ -36,6 +35,9 @@
 	static bool CheckAnalogChannel(UINT32 channel);
 	static bool CheckSolenoidChannel(UINT32 channel);
 
+  // NOT vxworks system clock ticks (returned by sysClkRateGet() from sysLib).
+  // TODO: Document what this actually is (has something to do with FPGA times).
+  // 40kHz clock?
 	static const UINT32 kSystemClockTicksPerMicrosecond = 40;
 	static const UINT32 kDigitalChannels = 14;
 	static const UINT32 kAnalogChannels = 8;
@@ -45,14 +47,19 @@
 	static const UINT32 kSolenoidModules = 2;
 	static const UINT32 kPwmChannels = 10;
 	static const UINT32 kRelayChannels = 8;
-	static const UINT32 kChassisSlots = 8;
+
 protected:
 	void AddToSingletonList();
+  // Subclasses that don't use the singleton list mechanism should make this
+  // public, but ones that do should keep it protected so that users can not
+  // delete the singleton instance(s).
+	virtual ~SensorBase();
 
 private:
 	DISALLOW_COPY_AND_ASSIGN(SensorBase);
 	static SensorBase *m_singletonList;
 	SensorBase *m_nextSingleton;
+  static ReentrantSemaphore m_singletonListSemaphore;
 };
 
 
diff --git a/aos/externals/WPILib/WPILib/SimpleRobot.h b/aos/externals/WPILib/WPILib/SimpleRobot.h
index d963805..88143a6 100644
--- a/aos/externals/WPILib/WPILib/SimpleRobot.h
+++ b/aos/externals/WPILib/WPILib/SimpleRobot.h
@@ -11,6 +11,10 @@
 
 /**
  * @todo If this is going to last until release, it needs a better name.
+ * Overridden Autonomous() and OperatorControl() methods are called at the appropriate time
+ * as the match proceeds. In the current implementation, the Autonomous code will run to
+ * completion before the OperatorControl code could start. In the future the Autonomous code
+ * might be spawned as a task, then killed at the end of the Autonomous period.
  */
 class SimpleRobot: public RobotBase
 {
diff --git a/aos/externals/WPILib/WPILib/Solenoid.cpp b/aos/externals/WPILib/WPILib/Solenoid.cpp
index 35813af..7a56a09 100644
--- a/aos/externals/WPILib/WPILib/Solenoid.cpp
+++ b/aos/externals/WPILib/WPILib/Solenoid.cpp
@@ -30,9 +30,10 @@
 	Resource::CreateResourceObject(&m_allocated, tSolenoid::kNumDO7_0Elements * kSolenoidChannels);
 
 	snprintf(buf, 64, "Solenoid %d (Module: %d)", m_channel, m_moduleNumber);
-	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1, buf) == ~0ul)
+	if (m_allocated->Allocate((m_moduleNumber - 1) * kSolenoidChannels
+                            + m_channel - 1,
+                            buf, this) == ~0ul)
 	{
-		CloneError(m_allocated);
 		return;
 	}
 
@@ -72,7 +73,8 @@
 {
 	if (CheckSolenoidModule(m_moduleNumber))
 	{
-		m_allocated->Free((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1);
+		m_allocated->Free((m_moduleNumber - 1) * kSolenoidChannels + m_channel - 1,
+                      this);
 	}
 }
 
diff --git a/aos/externals/WPILib/WPILib/SolenoidBase.cpp b/aos/externals/WPILib/WPILib/SolenoidBase.cpp
index cc1a2c4..1f38869 100644
--- a/aos/externals/WPILib/WPILib/SolenoidBase.cpp
+++ b/aos/externals/WPILib/WPILib/SolenoidBase.cpp
@@ -50,7 +50,7 @@
 }
 
 /**
- * Set the value of a solenoid.
+ * Set the value of 1 or more solenoids at the same time.
  * 
  * @param value The value you want to set on the module.
  * @param mask The channels you want to be affected.
@@ -63,8 +63,9 @@
 		Synchronized sync(m_semaphore);
 		UINT8 currentValue = m_fpgaSolenoidModule->readDO7_0(m_moduleNumber - 1, &localStatus);
 		// Zero out the values to change
-		currentValue = currentValue & ~mask;
-		currentValue = currentValue | (value & mask);
+		currentValue &= ~mask;
+    // Actually set the values.
+		currentValue |= value & mask;
 		m_fpgaSolenoidModule->writeDO7_0(m_moduleNumber - 1, currentValue, &localStatus);
 	}
 	wpi_setError(localStatus);
diff --git a/aos/externals/WPILib/WPILib/SolenoidBase.h b/aos/externals/WPILib/WPILib/SolenoidBase.h
index a7a67a6..a9fdf61 100644
--- a/aos/externals/WPILib/WPILib/SolenoidBase.h
+++ b/aos/externals/WPILib/WPILib/SolenoidBase.h
@@ -15,17 +15,25 @@
 /**
  * SolenoidBase class is the common base class for the Solenoid and
  * DoubleSolenoid classes.
+ * It also supports getting and setting the values of all solenoids on a given
+ * module at the same time directly.
  */
 class SolenoidBase : public SensorBase {
 public:
+	explicit SolenoidBase(UINT8 moduleNumber);
 	virtual ~SolenoidBase();
+
+	void Set(UINT8 value, UINT8 mask);
+
 	UINT8 GetAll();
+  /**
+   * Set the value of all of the solenoids at the same time.
+   *
+   * @param value The values you want to set all of the solenoids to.
+   */
+  void SetAll(UINT8 value) { Set(value, 0xFF); }
 
 protected:
-	explicit SolenoidBase(UINT8 moduleNumber);
-	void Set(UINT8 value, UINT8 mask);
-	virtual void InitSolenoid() = 0;
-
 	UINT32 m_moduleNumber; ///< Slot number where the module is plugged into the chassis.
 	static Resource *m_allocated;
 
diff --git a/aos/externals/WPILib/WPILib/Synchronized.cpp b/aos/externals/WPILib/WPILib/Synchronized.cpp
index eb17318..fd133b5 100644
--- a/aos/externals/WPILib/WPILib/Synchronized.cpp
+++ b/aos/externals/WPILib/WPILib/Synchronized.cpp
@@ -20,7 +20,7 @@
 	semTake(m_semaphore, WAIT_FOREVER);
 }
 
-Synchronized::Synchronized(ReentrantSemaphore& semaphore)
+Synchronized::Synchronized(const ReentrantSemaphore& semaphore)
 {
 	m_semaphore = semaphore.m_semaphore;
 	semTake(m_semaphore, WAIT_FOREVER);
diff --git a/aos/externals/WPILib/WPILib/Synchronized.h b/aos/externals/WPILib/WPILib/Synchronized.h
index 28cfbc3..4e44b0e 100644
--- a/aos/externals/WPILib/WPILib/Synchronized.h
+++ b/aos/externals/WPILib/WPILib/Synchronized.h
@@ -27,11 +27,15 @@
  *
  * This class is safe to use in static variables because it does not depend on
  * any other C++ static constructors or destructors.
+ *
+ * The instance methods are marked const because using this class from multiple
+ * threads at once is safe and they don't actually modify the value of any of
+ * the instance variables.
  */
 class ReentrantSemaphore
 {
 public:
-	explicit ReentrantSemaphore() {
+	ReentrantSemaphore() {
 		m_semaphore = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE);
 	}
 	~ReentrantSemaphore() {
@@ -42,7 +46,7 @@
 	 * Lock the semaphore, blocking until it's available.
 	 * @return 0 for success, -1 for error. If -1, the error will be in errno.
 	 */
-	int take() {
+	int take() const {
 		return semTake(m_semaphore, WAIT_FOREVER);
 	}
 
@@ -50,7 +54,7 @@
 	 * Unlock the semaphore.
 	 * @return 0 for success, -1 for error. If -1, the error will be in errno.
 	 */
-	int give() {
+	int give() const {
 		return semGive(m_semaphore);
 	}
 
@@ -83,8 +87,8 @@
 {
 public:
 	explicit Synchronized(SEM_ID);
-	explicit Synchronized(ReentrantSemaphore&);
-	virtual ~Synchronized();
+	explicit Synchronized(const ReentrantSemaphore&);
+	~Synchronized();
 private:
 	SEM_ID m_semaphore;
 
diff --git a/aos/externals/WPILib/WPILib/Task.cpp b/aos/externals/WPILib/WPILib/Task.cpp
index 4568246..5310d41 100644
--- a/aos/externals/WPILib/WPILib/Task.cpp
+++ b/aos/externals/WPILib/WPILib/Task.cpp
@@ -18,6 +18,7 @@
 
 /**
  * Create but don't launch a task.
+ * Does not use any floating point registers.
  * @param name The name of the task.  "FRC_" will be prepended to the task name.
  * @param function The address of the function to run as the new task.
  * @param priority The VxWorks priority for the task.
@@ -38,6 +39,9 @@
 	nUsageReporting::report(nUsageReporting::kResourceType_Task, instances, 0, m_taskName);
 }
 
+/**
+ * Does not use any floating point registers.
+ */
 Task::~Task()
 {
 	if (m_taskID != kInvalidTaskID) Stop();
@@ -47,18 +51,20 @@
 
 /**
  * Starts this task.
- * If it is already running or unable to start, it fails and returns false.
+ * Does not use any floating point registers.
+ * @return true on success
  */
 bool Task::Start(UINT32 arg0, UINT32 arg1, UINT32 arg2, UINT32 arg3, UINT32 arg4, 
 		UINT32 arg5, UINT32 arg6, UINT32 arg7, UINT32 arg8, UINT32 arg9)
 {
+  // Don't have to lock m_prioritySemaphore because this code isn't changing it.
 	m_taskID = taskSpawn(m_taskName,
 						m_priority,
 						VX_FP_TASK,							// options
 						m_stackSize,						// stack size
 						m_function,							// function to start
-						arg0, arg1, arg2, arg3, arg4,	// parameter 1 - pointer to this class
-						arg5, arg6, arg7, arg8, arg9);// additional unused parameters
+						arg0, arg1, arg2, arg3, arg4,	// parameters to pass to m_function
+						arg5, arg6, arg7, arg8, arg9);// additional parameters
 	bool ok = HandleError(m_taskID);
 	if (!ok) m_taskID = kInvalidTaskID;
 	return ok;
@@ -66,8 +72,7 @@
 
 /**
  * Restarts a running task.
- * If the task isn't started, it starts it.
- * @return false if the task is running and we are unable to kill the previous instance
+ * @return true on success
  */
 bool Task::Restart()
 {
@@ -75,8 +80,8 @@
 }
 
 /**
- * Kills the running task.
- * @returns true on success false if the task doesn't exist or we are unable to kill it.
+ * Makes sure that the task is not running.
+ * @returns true on success
  */
 bool Task::Stop()
 {
@@ -109,7 +114,7 @@
 
 /**
  * Pauses a running task.
- * Returns true on success, false if unable to pause or the task isn't running.
+ * Returns true on success
  */
 bool Task::Suspend()
 {
@@ -118,7 +123,7 @@
 
 /**
  * Resumes a paused task.
- * Returns true on success, false if unable to resume or if the task isn't running/paused.
+ * Returns true on success
  */
 bool Task::Resume()
 {
@@ -140,6 +145,7 @@
  */
 INT32 Task::GetPriority()
 {
+  Synchronized sync(m_prioritySemaphore);
 	if (HandleError(taskPriorityGet(m_taskID, &m_priority)))
 		return m_priority;
 	else
@@ -155,6 +161,7 @@
  */
 bool Task::SetPriority(INT32 priority)
 {
+  Synchronized sync(m_prioritySemaphore);
 	m_priority = priority;
 	return HandleError(taskPrioritySet(m_taskID, m_priority));
 }
diff --git a/aos/externals/WPILib/WPILib/Task.h b/aos/externals/WPILib/WPILib/Task.h
index 03c9555..d1ad259 100644
--- a/aos/externals/WPILib/WPILib/Task.h
+++ b/aos/externals/WPILib/WPILib/Task.h
@@ -9,10 +9,14 @@
 
 #include "ErrorBase.h"
 #include <vxWorks.h>
+#include "Synchronized.h"
 
 /**
- * WPI task is a wrapper for the native Task object.
- * All WPILib tasks are managed by a static task manager for simplified cleanup.
+ * WPI task is a wrapper for a native VxWorks task.
+ *
+ * Some functions (documented) are guaranteed not to use any floating point so
+ * that it is safe to use them from tasks that do not have the VX_FP_TASK flag
+ * set (like during startup).
  **/
 class Task : public ErrorBase
 {
@@ -47,6 +51,7 @@
 	INT32 m_taskID;
 	UINT32 m_stackSize;
 	INT32 m_priority;
+  ReentrantSemaphore m_prioritySemaphore;
 	bool HandleError(STATUS results);
 	DISALLOW_COPY_AND_ASSIGN(Task);
 };
diff --git a/aos/externals/WPILib/WPILib/Timer.cpp b/aos/externals/WPILib/WPILib/Timer.cpp
index e9fcde7..7638b59 100644
--- a/aos/externals/WPILib/WPILib/Timer.cpp
+++ b/aos/externals/WPILib/WPILib/Timer.cpp
@@ -12,6 +12,7 @@
 
 #include "Synchronized.h"
 #include "Utility.h"
+#include "Global.h"
 
 /**
  * Pause the task for a specified time.
@@ -180,7 +181,7 @@
 {
 	// FPGA returns the timestamp in microseconds
 	// Call the helper GetFPGATime() in Utility.cpp
-	return GetFPGATime() * 1.0e-6;
+	return Global::GetInstance()->GetFPGATime() * 1.0e-6;
 }
 
 // Internal function that reads the PPC timestamp counter.
diff --git a/aos/externals/WPILib/WPILib/Utility.cpp b/aos/externals/WPILib/WPILib/Utility.cpp
index 5ce84f9..680da97 100644
--- a/aos/externals/WPILib/WPILib/Utility.cpp
+++ b/aos/externals/WPILib/WPILib/Utility.cpp
@@ -7,34 +7,34 @@
 #include "Utility.h"
 
 #include "NetworkCommunication/FRCComm.h"
-#include "ChipObject.h"
 #include "Task.h"
 #include <dbgLib.h>
 #include <stdio.h>
+#include <taskLib.h>
 #include <sysSymTbl.h>
 #include "nivision.h"
 
-#define DBG_DEMANGLE_PRINT_LEN 256  /* Num chars of demangled names to print */
+#define DBG_DEMANGLE_PRINT_LEN MAX_SYS_SYM_LEN  /* Num chars of demangled names to print */
 
 extern "C"
 {
 	extern char * cplusDemangle (char *source, char *dest, INT32 n);
 }
 
-char *wpi_getLabel(UINT addr, INT32 *found)
+void wpi_getLabel(UINT addr, char *label, INT32 *found)
 {
 	INT32 pVal;
 	SYM_TYPE pType;
 	char name[MAX_SYS_SYM_LEN + 1];
-	static char label[DBG_DEMANGLE_PRINT_LEN + 1 + 11];
-	bzero(label, DBG_DEMANGLE_PRINT_LEN + 1 + 11);
+  static const size_t kLabelSize = DBG_DEMANGLE_PRINT_LEN + 1 + 11;
+	bzero(label, kLabelSize);
 
 	if (symFindByValue(sysSymTbl, addr, name, &pVal, &pType) == OK)
 	{
-		cplusDemangle(name, label, sizeof(label) - 11);
+		cplusDemangle(name, label, kLabelSize - 11);
 		if ((UINT)pVal != addr)
 		{
-			sprintf(&label[strlen(label)], "+0x%04x", addr-pVal);
+			snprintf(label + strlen(label), kLabelSize - strlen(label), "+0x%04x", addr-pVal);
 			if (found) *found = 2;
 		}
 		else
@@ -44,11 +44,9 @@
 	}
 	else
 	{
-		sprintf(label, "0x%04x", addr);
+		snprintf(label, kLabelSize, "0x%04x", addr);
 		if (found) *found = 0;
 	}
-
-	return label;
 }
 /*
 static void wpiTracePrint(INSTR *caller, INT32 func, INT32 nargs, INT32 *args, INT32 taskId, BOOL isKernelAdrs)
@@ -56,15 +54,16 @@
 	char buf [MAX_SYS_SYM_LEN * 2];
 	INT32 ix;
 	INT32 len = 0;
-	len += sprintf (&buf [len], "%s <%#010x>: ", wpi_getLabel((UINT)caller), (INT32)caller);
-	len += sprintf (&buf [len], "%s <%#010x> (", wpi_getLabel((UINT)func), func);
+	len += snprintf (&buf [len], sizeof(buf) - len, "%s <%#010x>: ", wpi_getLabel((UINT)caller), (INT32)caller);
+	len += snprintf (&buf [len], sizeof(buf) - len, "%s <%#010x> (", wpi_getLabel((UINT)func), func);
 	for (ix = 0; ix < nargs; ix++)
 	{
-		if (ix != 0)
-			len += sprintf (&buf [len], ", ");
-		len += sprintf (&buf [len], "%#x", args [ix]);
+		if (ix != 0) {
+			len += snprintf (&buf [len], sizeof(buf) - len, ", ");
+    }
+		len += snprintf (&buf [len], sizeof(buf) - len, "%#x", args [ix]);
 	}
-	len += sprintf (&buf [len], ")\n");
+	len += snprintf (&buf [len], sizeof(buf) - len, ")\n");
 
 	printf(buf);
 }
@@ -77,7 +76,8 @@
 	INT32 nameFound = 0;
 	INT32 params = 0;
 	INT32 totalnargs = nargs;
-	char *funcName = wpi_getLabel((UINT)func, &nameFound);
+  char funcName[DBG_DEMANGLE_PRINT_LEN + 1 + 11];
+	wpi_getLabel((UINT)func, funcName, &nameFound);
 	// Ignore names that are not exact symbol address matches.
 	if (nameFound != 1) return;
 
@@ -107,23 +107,24 @@
 	}
 	char *funcNameEnd = strchr(funcName, '(');
 	*funcNameEnd = 0;
-	len += sprintf (&buf [len], funcName);
+	len += snprintf (buf + len, sizeof(buf) - len, funcName);
 
 	// If this is a member function, print out the this pointer value.
 	if (totalnargs - params == 1)
 	{
-		len += sprintf (&buf [len], "<this=%#x>", args [0]);
+		len += snprintf (buf + len, sizeof(buf) - len, "<this=%#x>", args [0]);
 	}
 
 	// Print out the argument values.
-	len += sprintf (&buf [len], "(");
+	len += snprintf (buf + len, sizeof(buf) - len, "(");
 	for (ix = totalnargs - params; ix < nargs; ix++)
 	{
-		if (ix != totalnargs - params)
-			len += sprintf (&buf [len], ", ");
-		len += sprintf (&buf [len], "%#x", args [ix]);
+		if (ix != totalnargs - params) {
+			len += snprintf (buf + len, sizeof(buf) - len, ", ");
+    }
+		len += snprintf (buf + len, sizeof(buf) - len, "%#x", args [ix]);
 	}
-	len += sprintf (&buf [len], ")\n");
+	len += snprintf (buf + len, sizeof(buf) - len, ")\n");
 
 	printf(buf);
 }
@@ -135,7 +136,11 @@
 
 static INT32 wpiStackTask(INT32 taskId)
 {
-	taskDelay(1);
+  // Make sure it's suspended in spite of any scheduler weirdness or whatever.
+  while (!taskIsSuspended(taskId)) {
+	  taskDelay(1);
+  }
+
 	//tt(taskId);
 
 	REG_SET regs;
@@ -212,10 +217,10 @@
 		// If an error message was specified, include it
 		// Build error string
 		if(message != NULL) {
-			sprintf(error, "Assertion failed: \"%s\", \"%s\" failed in %s() in %s at line %d\n", 
+			snprintf(error, sizeof(error), "Assertion failed: \"%s\", \"%s\" failed in %s() in %s at line %d\n",
 							 message, conditionText, funcName, fileName, lineNumber);
 		} else {
-			sprintf(error, "Assertion failed: \"%s\" in %s() in %s at line %d\n", 
+			snprintf(error, sizeof(error), "Assertion failed: \"%s\" in %s() in %s at line %d\n",
 							 conditionText, funcName, fileName, lineNumber);
 		}
 		
@@ -248,10 +253,10 @@
 	// If an error message was specified, include it
 	// Build error string
 	if(message != NULL) {
-		sprintf(error, "Assertion failed: \"%s\", \"%d\" %s \"%d\" in %s() in %s at line %d\n", 
+		snprintf(error, sizeof(error), "Assertion failed: \"%s\", \"%d\" %s \"%d\" in %s() in %s at line %d\n",
 						 message, valueA, equalityType, valueB, funcName, fileName, lineNumber);
 	} else {
-		sprintf(error, "Assertion failed: \"%d\" %s \"%d\" in %s() in %s at line %d\n", 
+		snprintf(error, sizeof(error), "Assertion failed: \"%d\" %s \"%d\" in %s() in %s at line %d\n",
 						 valueA, equalityType, valueB, funcName, fileName, lineNumber);
 	}
 	
@@ -302,137 +307,3 @@
 	}
 	return valueA != valueB;
 }
-
-
-/**
- * Return the FPGA Version number.
- * For now, expect this to be competition year.
- * @return FPGA Version number.
- */
-UINT16 GetFPGAVersion()
-{
-	tRioStatusCode status = 0;
-	tGlobal *global = tGlobal::create(&status);
-	UINT16 version = global->readVersion(&status);
-	delete global;
-	wpi_setGlobalError(status);
-	return version;
-}
-
-/**
- * Return the FPGA Revision number.
- * The format of the revision is 3 numbers.
- * The 12 most significant bits are the Major Revision.
- * the next 8 bits are the Minor Revision.
- * The 12 least significant bits are the Build Number.
- * @return FPGA Revision number.
- */
-UINT32 GetFPGARevision()
-{
-	tRioStatusCode status = 0;
-	tGlobal *global = tGlobal::create(&status);
-	UINT32 revision = global->readRevision(&status);
-	delete global;
-	wpi_setGlobalError(status);
-	return revision;
-}
-
-/**
- * Read the microsecond-resolution timer on the FPGA.
- * 
- * @return The current time in microseconds according to the FPGA (since FPGA reset).
- */
-UINT32 GetFPGATime()
-{
-	tRioStatusCode status = 0;
-	tGlobal *global = tGlobal::create(&status);
-	UINT32 time = global->readLocalTime(&status);
-	delete global;
-	wpi_setGlobalError(status);
-	return time;
-}
-
-// RT hardware access functions exported from ni_emb.out
-extern "C"
-{
-	INT32 UserSwitchInput(INT32 nSwitch);
-	INT32 LedInput(INT32 led);
-	INT32 LedOutput(INT32 led, INT32 value);
-}
-
-/**
- * Read the value of the USER1 DIP switch on the cRIO.
- */
-INT32 GetRIOUserSwitch()
-{
-	INT32 switchValue = UserSwitchInput(0);
-	wpi_assert(switchValue >= 0);
-	return switchValue > 0;
-}
-
-/**
- * Set the state of the USER1 status LED on the cRIO.
- */
-void SetRIOUserLED(UINT32 state)
-{
-	LedOutput(0, state > 0);
-}
-
-/**
- * Get the current state of the USER1 status LED on the cRIO.
- * @return The curent state of the USER1 LED.
- */
-INT32 GetRIOUserLED()
-{
-	return LedInput(0);
-}
-
-/**
- * Toggle the state of the USER1 status LED on the cRIO.
- * @return The new state of the USER1 LED.
- */
-INT32 ToggleRIOUserLED()
-{
-	INT32 ledState = !GetRIOUserLED();
-	SetRIOUserLED(ledState);
-	return ledState;
-}
-
-/**
- * Set the state of the FPGA status LED on the cRIO.
- */
-void SetRIO_FPGA_LED(UINT32 state)
-{
-	tRioStatusCode status = 0;
-	tGlobal *global = tGlobal::create(&status);
-	global->writeFPGA_LED(state, &status);
-	wpi_setGlobalError(status);
-	delete global;
-}
-
-/**
- * Get the current state of the FPGA status LED on the cRIO.
- * @return The curent state of the FPGA LED.
- */
-INT32 GetRIO_FPGA_LED()
-{
-	tRioStatusCode status = 0;
-	tGlobal *global = tGlobal::create(&status);
-	bool ledValue = global->readFPGA_LED(&status);
-	wpi_setGlobalError(status);
-	delete global;
-	return ledValue;
-}
-
-/**
- * Toggle the state of the FPGA status LED on the cRIO.
- * @return The new state of the FPGA LED.
- */
-INT32 ToggleRIO_FPGA_LED()
-{
-	INT32 ledState = !GetRIO_FPGA_LED();
-	SetRIO_FPGA_LED(ledState);
-	return ledState;
-}
-
-
diff --git a/aos/externals/WPILib/WPILib/Utility.h b/aos/externals/WPILib/WPILib/Utility.h
index 01bcbff..4462b7c 100644
--- a/aos/externals/WPILib/WPILib/Utility.h
+++ b/aos/externals/WPILib/WPILib/Utility.h
@@ -22,20 +22,10 @@
 bool wpi_assertEqual_impl(int valueA, int valueB, const char *message, const char *fileName,UINT32 lineNumber, const char *funcName);
 bool wpi_assertNotEqual_impl(int valueA, int valueB, const char *message, const char *fileName,UINT32 lineNumber, const char *funcName);
 
-char *wpi_getLabel(UINT addr, INT32 *found = NULL);
+// Will use up to (DBG_DEMANGLE_PRINT_LEN + 1 + 11) of label.
+void wpi_getLabel(UINT addr, char *label, INT32 *found = NULL);
 void wpi_selfTrace();
 void wpi_suspendOnAssertEnabled(bool enabled);
 void wpi_stackTraceOnAssertEnable(bool enabled);
 
-UINT16 GetFPGAVersion();
-UINT32 GetFPGARevision();
-UINT32 GetFPGATime();
-INT32 GetRIOUserSwitch();
-void SetRIOUserLED(UINT32 state);
-INT32 GetRIOUserLED();
-INT32 ToggleRIOUserLED();
-void SetRIO_FPGA_LED(UINT32 state);
-INT32 GetRIO_FPGA_LED();
-INT32 ToggleRIO_FPGA_LED();
-
 #endif // UTILITY_H_
diff --git a/aos/externals/WPILib/WPILib/networktables2/stream/FDIOStream.cpp b/aos/externals/WPILib/WPILib/networktables2/stream/FDIOStream.cpp
index 35d3c41..5f9fa3e 100644
--- a/aos/externals/WPILib/WPILib/networktables2/stream/FDIOStream.cpp
+++ b/aos/externals/WPILib/WPILib/networktables2/stream/FDIOStream.cpp
@@ -12,7 +12,7 @@
 #include <errno.h>
 #include <stdlib.h>
 #ifdef _WRS_KERNEL
-#include <iolib.h>
+#include <ioLib.h>
 #else
 #include <unistd.h>
 #endif
diff --git a/doc/wpilib-issues.txt b/doc/wpilib-issues.txt
new file mode 100644
index 0000000..1b46940
--- /dev/null
+++ b/doc/wpilib-issues.txt
@@ -0,0 +1,6 @@
+sprintf
+ErrorBase/Error not thread safe (aka CANJaguar)
+all of the sync issues last year
+Module not thread safe
+
+compressor turned on as soon as power was turned on (2 times in a row)
diff --git a/frc971/crio/crio.gyp b/frc971/crio/crio.gyp
index 9542e0b..62d88bc 100644
--- a/frc971/crio/crio.gyp
+++ b/frc971/crio/crio.gyp
@@ -6,6 +6,7 @@
       'type': 'static_library',
       'dependencies': [
         '<(EXTERNALS):WPILib',
+        '<(EXTERNALS):libgcc-4.5.2',
       ],
     },
     {