+ SHORTREL(&gTimers_ListLock);
+
+ if( t ) {
+ Timer->bActive = 0;
+ LOG("%p removed %p", __builtin_return_address(0), Timer);
+ }
+ else
+ LOG("%p tried to remove %p (already complete)", __builtin_return_address(0), Timer);
+}
+
+/**
+ * \brief Allocate a timer object, but don't schedule it
+ */
+tTimer *Time_AllocateTimer(tTimerCallback *Callback, void *Argument)
+{
+ tTimer *ret = malloc(sizeof(tTimer));
+ if( !ret ) return NULL;
+ Time_InitTimer(ret, Callback, Argument);
+ return ret;
+}
+
+/**
+ * \brief Initialise a timer
+ * \note Mostly an internal function
+ */
+void Time_InitTimer(tTimer *Timer, tTimerCallback *Callback, void *Argument)
+{
+ if(Callback == NULL)
+ Argument = Proc_GetCurThread();
+ Timer->FiresAfter = 0;
+ Timer->Callback = Callback;
+ Timer->Argument = Argument;
+// memset( &Timer->Lock, 0, sizeof(Timer->Lock) );
+ Timer->bActive = 0;
+}
+
+/**
+ * \brief Free an allocated timer
+ */
+void Time_FreeTimer(tTimer *Timer)
+{
+ if( !Timer ) return ;
+ Time_RemoveTimer( Timer ); // Just in case
+
+ // Ensures that we don't free until the timer callback has started
+ while( Timer->bActive ) Threads_Yield();
+ // Release won't be needed, as nothing should be waiting on it
+// Mutex_Acquire( &Timer->Lock );
+
+ // Free timer
+ free(Timer);
+ LOG("%p deallocated %p", __builtin_return_address(0), Timer);