summaryrefslogtreecommitdiff
path: root/src/common/timer.c
diff options
context:
space:
mode:
authorFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-07-15 01:41:49 +0000
committerFlavioJS <FlavioJS@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-07-15 01:41:49 +0000
commit5f432aa0e316f5afb293f25f3e74c79a23a661f4 (patch)
tree670a7f458f6bc3a017b9eda858024eb778587a4e /src/common/timer.c
parent528ea8ab556b8fa53a49c3cbf72b7e9a2a678c5e (diff)
downloadhercules-5f432aa0e316f5afb293f25f3e74c79a23a661f4.tar.gz
hercules-5f432aa0e316f5afb293f25f3e74c79a23a661f4.tar.bz2
hercules-5f432aa0e316f5afb293f25f3e74c79a23a661f4.tar.xz
hercules-5f432aa0e316f5afb293f25f3e74c79a23a661f4.zip
* Fixed pop_timer_heap using max heap comparisons instead of min heap comparisons and protected timer functions against improper use. (should fix bugreport:1833 bugreport:1841)
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@12956 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/common/timer.c')
-rw-r--r--src/common/timer.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/src/common/timer.c b/src/common/timer.c
index cf594ef6d..df227cb57 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -195,12 +195,12 @@ bool pop_timer_heap(int tid)
if( timer_heap[pos] == tid )
break;// found the timer
- if( left < timer_heap_num && DIFF_TICK(timer_data[tid].tick, timer_data[timer_heap[left]].tick) <= 0 )
+ if( left < timer_heap_num && DIFF_TICK(timer_data[tid].tick, timer_data[timer_heap[left]].tick) >= 0 )
{// try left child
pos = left;
continue;
}
- if( right < timer_heap_num && DIFF_TICK(timer_data[tid].tick, timer_data[timer_heap[right]].tick) <= 0 )
+ if( right < timer_heap_num && DIFF_TICK(timer_data[tid].tick, timer_data[timer_heap[right]].tick) >= 0 )
{// try right child
pos = right;
continue;
@@ -214,7 +214,7 @@ bool pop_timer_heap(int tid)
return false;// not found
parent = BHEAP_PARENT(pos);
right = BHEAP_RIGHT(parent);
- if( pos != right && right < timer_heap_num && DIFF_TICK(timer_data[tid].tick, timer_data[timer_heap[right]].tick) <= 0 )
+ if( pos != right && right < timer_heap_num && DIFF_TICK(timer_data[tid].tick, timer_data[timer_heap[right]].tick) >= 0 )
break;// try this right
pos = parent;
}
@@ -294,6 +294,26 @@ bool adjust_tick(unsigned int* tick)
return true;
}
+/// Releases a timer.
+static
+void release_timer(int tid)
+{
+ if( timer_data[tid].type == 0 )
+ return;// already released
+
+ memset(&timer_data[tid], 0, sizeof(struct TimerData));
+ if( free_timer_list_num >= free_timer_list_max )
+ {
+ free_timer_list_max += 256;
+ if( free_timer_list )
+ RECREATE(free_timer_list, int, free_timer_list_max);
+ else
+ CREATE(free_timer_list, int, free_timer_list_max);
+ memset(free_timer_list + (free_timer_list_max - 256), 0, sizeof(int)*256);
+ }
+ free_timer_list[free_timer_list_num++] = tid;
+}
+
/// Returns a free timer id.
static int acquire_timer(void)
{
@@ -383,7 +403,7 @@ int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr data, i
/// Retrieves internal timer data
const struct TimerData* get_timer(int tid)
{
- if( tid >= 0 && tid < timer_data_num )
+ if( tid >= 0 && tid < timer_data_num && timer_data[tid].type != 0 )
return &timer_data[tid];
return NULL;
}
@@ -393,7 +413,7 @@ const struct TimerData* get_timer(int tid)
/// Returns 0 on success, < 0 on failure.
int delete_timer(int tid, TimerFunc func)
{
- if( tid < 0 || tid >= timer_data_num )
+ if( tid < 0 || tid >= timer_data_num || timer_data[tid].type == 0 )
{
ShowError("delete_timer error : no such timer %d (%08x(%s))\n", tid, (int)func, search_timer_func_list(func));
return -1;
@@ -404,9 +424,11 @@ int delete_timer(int tid, TimerFunc func)
return -2;
}
- timer_data[tid].func = NULL;
- timer_data[tid].type = TIMER_ONCE_AUTODEL;
-
+ if( timer_data[tid].type&TIMER_REMOVE_HEAP )
+ // timer func being executed, make sure it's marked for removal when it ends
+ timer_data[tid].type = TIMER_FORCE_REMOVE|TIMER_REMOVE_HEAP;
+ else if( pop_timer_heap(tid) )
+ release_timer(tid);
return 0;
}
@@ -421,6 +443,11 @@ int addtick_timer(int tid, unsigned int tick)
/// Returns the new tick value, or -1 if it fails.
int settick_timer(int tid, unsigned int tick)
{
+ if( tid < 0 || tid >= timer_data_num || timer_data[tid].type == 0 )
+ {
+ ShowError("settick_timer error : no such timer %d\n", tid);
+ return -1;
+ }
if( timer_data[tid].tick == tick )
return tick;
@@ -431,7 +458,8 @@ int settick_timer(int tid, unsigned int tick)
}
pop_timer_heap(tid);
if( tick == -1 )
- tick = 0;
+ tick = 0;// -1 is reserved for error
+ timer_data[tid].type &= ~TIMER_REMOVE_HEAP;
timer_data[tid].tick = tick;
push_timer_heap(tid);
return tick;
@@ -470,24 +498,15 @@ int do_timer(unsigned int tick)
}
// in the case the function didn't change anything...
- if( timer_data[tid].type & TIMER_REMOVE_HEAP )
+ if( timer_data[tid].type & TIMER_REMOVE_HEAP || timer_data[tid].type == TIMER_FORCE_REMOVE )
{
timer_data[tid].type &= ~TIMER_REMOVE_HEAP;
switch( timer_data[tid].type )
{
+ case TIMER_FORCE_REMOVE:
case TIMER_ONCE_AUTODEL:
- timer_data[tid].type = 0;
- if( free_timer_list_num >= free_timer_list_max )
- {
- free_timer_list_max += 256;
- if( free_timer_list )
- RECREATE(free_timer_list, int, free_timer_list_max);
- else
- CREATE(free_timer_list, int, free_timer_list_max);
- memset(free_timer_list + (free_timer_list_max - 256), 0, sizeof(int)*256);
- }
- free_timer_list[free_timer_list_num++] = tid;
+ release_timer(tid);
break;
case TIMER_INTERVAL:
if( DIFF_TICK(timer_data[tid].tick, tick) < -1000 )