aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2015-05-11 17:56:03 +0200
committerRickard Green <rickard@erlang.org>2015-05-12 17:26:37 +0200
commit849a2ed2db2bd54422ec9284468f80cc86978974 (patch)
tree10f63d4ef099645145158301c145372ecfbbfbc2 /erts/emulator/beam
parent9c78f149517dc02457d4c59e90bc9b03d411e28c (diff)
downloadotp-849a2ed2db2bd54422ec9284468f80cc86978974.tar.gz
otp-849a2ed2db2bd54422ec9284468f80cc86978974.tar.bz2
otp-849a2ed2db2bd54422ec9284468f80cc86978974.zip
Timer fixes, documentation, and test cases
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/erl_alloc.c16
-rw-r--r--erts/emulator/beam/erl_hl_timer.c66
-rw-r--r--erts/emulator/beam/time.c60
3 files changed, 79 insertions, 63 deletions
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 71902c2f9f..7d099997d8 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -2331,6 +2331,22 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
&size.processes_used,
fi,
ERTS_ALC_T_MSG_REF);
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_LL_PTIMER);
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_HL_PTIMER);
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_BIF_TIMER);
+ add_fix_values(&size.processes,
+ &size.processes_used,
+ fi,
+ ERTS_ALC_T_ABIF_TIMER);
}
if (want.atom || want.atom_used) {
diff --git a/erts/emulator/beam/erl_hl_timer.c b/erts/emulator/beam/erl_hl_timer.c
index 2245799819..f1806d25be 100644
--- a/erts/emulator/beam/erl_hl_timer.c
+++ b/erts/emulator/beam/erl_hl_timer.c
@@ -850,8 +850,6 @@ hl_timer_destroy(ErtsHLTimer *tmr)
if (!(roflgs & ERTS_TMR_ROFLG_BIF_TMR))
erts_free(ERTS_ALC_T_HL_PTIMER, tmr);
else {
- if (tmr->btm.bp)
- free_message_buffer(tmr->btm.bp);
if (roflgs & ERTS_TMR_ROFLG_PRE_ALC)
bif_timer_pre_free(tmr);
else if (roflgs & ERTS_TMR_ROFLG_ABIF_TMR)
@@ -898,10 +896,6 @@ schedule_hl_timer_destroy(ErtsHLTimer *tmr, Uint32 roflgs)
* Message buffer can be dropped at
* once...
*/
- if (tmr->btm.bp) {
- free_message_buffer(tmr->btm.bp);
- tmr->btm.bp = NULL;
- }
size = sizeof(ErtsHLTimer);
}
@@ -1121,6 +1115,7 @@ hlt_bif_timer_timeout(ErtsHLTimer *tmr, Uint32 roflgs)
{
ErtsProcLocks proc_locks = ERTS_PROC_LOCKS_MSG_SEND;
Process *proc;
+ int queued_message = 0;
int dec_refc = 0;
Uint32 is_reg_name = (roflgs & ERTS_TMR_ROFLG_REG_NAME);
ERTS_HLT_ASSERT(roflgs & ERTS_TMR_ROFLG_BIF_TMR);
@@ -1159,6 +1154,7 @@ hlt_bif_timer_timeout(ErtsHLTimer *tmr, Uint32 roflgs)
#endif
);
erts_smp_proc_unlock(proc, ERTS_PROC_LOCKS_MSG_SEND);
+ queued_message = 1;
proc_locks &= ~ERTS_PROC_LOCKS_MSG_SEND;
tmr->btm.bp = NULL;
if (tmr->btm.proc_tree.parent != ERTS_HLT_PFIELD_NOT_IN_TABLE) {
@@ -1172,6 +1168,8 @@ hlt_bif_timer_timeout(ErtsHLTimer *tmr, Uint32 roflgs)
if (dec_refc)
hl_timer_pre_dec_refc(tmr);
}
+ if (!queued_message && tmr->btm.bp)
+ free_message_buffer(tmr->btm.bp);
}
static ERTS_INLINE void
@@ -1689,6 +1687,8 @@ setup_bif_timer(Process *c_p, ErtsMonotonicTime timeout_pos,
rcvr, ERTS_PROC_LOCK_BTM,
ERTS_P2P_FLG_INC_REFC);
if (!proc) {
+ if (tmr->btm.bp)
+ free_message_buffer(tmr->btm.bp);
hlt_delete_timer(esdp, tmr);
hl_timer_destroy(tmr);
}
@@ -1721,6 +1721,9 @@ cancel_bif_timer(ErtsHLTimer *tmr)
if (state != ERTS_TMR_STATE_ACTIVE)
return 0;
+ if (tmr->btm.bp)
+ free_message_buffer(tmr->btm.bp);
+
res = -1;
roflgs = tmr->head.roflgs;
@@ -1834,18 +1837,25 @@ access_sched_local_btm(Process *c_p, Eterm pid,
if (!async)
hsz += REF_THING_SIZE;
else {
- if (is_non_value(tref))
+ if (is_non_value(tref) || proc != c_p)
hsz += REF_THING_SIZE;
hsz += 1; /* upgrade to 3-tuple */
}
if (time_left > (Sint64) MAX_SMALL)
hsz += ERTS_SINT64_HEAP_SIZE(time_left);
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- proc,
- &proc_locks);
+ if (proc == c_p) {
+ bp = NULL;
+ ohp = NULL;
+ hp = HAlloc(c_p, hsz);
+ }
+ else {
+ hp = erts_alloc_message_heap(hsz,
+ &bp,
+ &ohp,
+ proc,
+ &proc_locks);
+ }
#ifdef ERTS_HLT_DEBUG
hp_end = hp + hsz;
@@ -1871,7 +1881,7 @@ access_sched_local_btm(Process *c_p, Eterm pid,
}
else {
Eterm tag = cancel ? am_cancel_timer : am_read_timer;
- if (is_value(tref))
+ if (is_value(tref) && proc == c_p)
ref = tref;
else {
write_ref_thing(hp,
@@ -1987,8 +1997,6 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
}
else {
Eterm tag, res, msg;
- ErlOffHeap *ohp;
- ErlHeapFragment* bp;
Uint hsz;
Eterm *hp;
ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN;
@@ -1997,11 +2005,7 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
if (time_left > (Sint64) MAX_SMALL)
hsz += ERTS_SINT64_HEAP_SIZE(time_left);
- hp = erts_alloc_message_heap(hsz,
- &bp,
- &ohp,
- c_p,
- &proc_locks);
+ hp = HAlloc(c_p, hsz);
if (cancel)
tag = am_cancel_timer;
else
@@ -2016,7 +2020,7 @@ try_access_sched_remote_btm(ErtsSchedulerData *esdp,
msg = TUPLE3(hp, tag, tref, res);
- erts_queue_message(c_p, &proc_locks, bp,
+ erts_queue_message(c_p, &proc_locks, NULL,
msg, NIL
#ifdef USE_VM_PROBES
, NIL
@@ -2166,7 +2170,7 @@ parse_bif_timer_options(Eterm option_list, int *async, int *info,
if (async)
*async = 0;
if (info)
- *info = 0;
+ *info = 1;
if (abs)
*abs = 0;
if (accessor)
@@ -2235,13 +2239,19 @@ exit_cancel_bif_timer(ErtsHLTimer *tmr, void *vesdp)
tmr->btm.proc_tree.parent = ERTS_HLT_PFIELD_NOT_IN_TABLE;
if (sid == (Uint32) esdp->no) {
- if (state == ERTS_TMR_STATE_ACTIVE)
+ if (state == ERTS_TMR_STATE_ACTIVE) {
+ if (tmr->btm.bp)
+ free_message_buffer(tmr->btm.bp);
hlt_delete_timer(esdp, tmr);
+ }
hl_timer_dec_refc(tmr, roflgs);
}
else {
- if (state == ERTS_TMR_STATE_ACTIVE)
+ if (state == ERTS_TMR_STATE_ACTIVE) {
+ if (tmr->btm.bp)
+ free_message_buffer(tmr->btm.bp);
queue_canceled_timer(esdp, sid, (ErtsTimer *) tmr);
+ }
else
hl_timer_dec_refc(tmr, roflgs);
}
@@ -2415,7 +2425,7 @@ BIF_RETTYPE send_after_3(BIF_ALIST_3)
tres = parse_timeout_pos(ERTS_PROC_GET_SCHDATA(BIF_P), BIF_ARG_1, NULL,
0, &timeout_pos, &short_time);
if (tres != 0)
- BIF_ERROR(BIF_P, tres < 0 ? BADARG : SYSTEM_LIMIT);
+ BIF_ERROR(BIF_P, BADARG);
return setup_bif_timer(BIF_P, timeout_pos, short_time,
BIF_ARG_2, BIF_ARG_2, BIF_ARG_3, 0);
@@ -2433,7 +2443,7 @@ BIF_RETTYPE send_after_4(BIF_ALIST_4)
tres = parse_timeout_pos(ERTS_PROC_GET_SCHDATA(BIF_P), BIF_ARG_1, NULL,
abs, &timeout_pos, &short_time);
if (tres != 0)
- BIF_ERROR(BIF_P, tres < 0 ? BADARG : SYSTEM_LIMIT);
+ BIF_ERROR(BIF_P, BADARG);
return setup_bif_timer(BIF_P, timeout_pos, short_time,
BIF_ARG_2, accessor, BIF_ARG_3, 0);
@@ -2447,7 +2457,7 @@ BIF_RETTYPE start_timer_3(BIF_ALIST_3)
tres = parse_timeout_pos(ERTS_PROC_GET_SCHDATA(BIF_P), BIF_ARG_1, NULL,
0, &timeout_pos, &short_time);
if (tres != 0)
- BIF_ERROR(BIF_P, tres < 0 ? BADARG : SYSTEM_LIMIT);
+ BIF_ERROR(BIF_P, BADARG);
return setup_bif_timer(BIF_P, timeout_pos, short_time,
BIF_ARG_2, BIF_ARG_2, BIF_ARG_3, !0);
@@ -2465,7 +2475,7 @@ BIF_RETTYPE start_timer_4(BIF_ALIST_4)
tres = parse_timeout_pos(ERTS_PROC_GET_SCHDATA(BIF_P), BIF_ARG_1, NULL,
abs, &timeout_pos, &short_time);
if (tres != 0)
- BIF_ERROR(BIF_P, tres < 0 ? BADARG : SYSTEM_LIMIT);
+ BIF_ERROR(BIF_P, BADARG);
return setup_bif_timer(BIF_P, timeout_pos, short_time,
BIF_ARG_2, accessor, BIF_ARG_3, !0);
diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c
index ea19d8b362..8bffdedb2b 100644
--- a/erts/emulator/beam/time.c
+++ b/erts/emulator/beam/time.c
@@ -135,39 +135,40 @@ struct ErtsTimerWheel_ {
ErtsMonotonicTime next_timeout_time;
};
-/* get the time (in units of TIW_ITIME) to the next timeout,
- or -1 if there are no timeouts */
-
static ERTS_INLINE ErtsMonotonicTime
-find_next_timeout(ErtsTimerWheel *tiw,
- ErtsMonotonicTime curr_time,
- ErtsMonotonicTime max_search_time)
+find_next_timeout(ErtsSchedulerData *esdp,
+ ErtsTimerWheel *tiw,
+ int search_all,
+ ErtsMonotonicTime curr_time, /* When !search_all */
+ ErtsMonotonicTime max_search_time) /* When !search_all */
{
int start_ix, tiw_pos_ix;
ErtsTWheelTimer *p;
- int true_min_timeout;
+ int true_min_timeout = 0;
ErtsMonotonicTime min_timeout, min_timeout_pos, slot_timeout_pos;
- if (tiw->true_next_timeout_time)
- return tiw->next_timeout_time;
-
if (tiw->nto == 0) { /* no timeouts in wheel */
- true_min_timeout = 0;
- min_timeout_pos = ERTS_MONOTONIC_TO_CLKTCKS(curr_time + ERTS_MONOTONIC_DAY);
+ if (!search_all)
+ min_timeout_pos = tiw->pos;
+ else {
+ curr_time = erts_get_monotonic_time(esdp);
+ tiw->pos = min_timeout_pos = ERTS_MONOTONIC_TO_CLKTCKS(curr_time);
+ }
+ min_timeout_pos += ERTS_MONOTONIC_TO_CLKTCKS(ERTS_MONOTONIC_DAY);
goto found_next;
}
- slot_timeout_pos = tiw->pos;
- min_timeout_pos = ERTS_MONOTONIC_TO_CLKTCKS(curr_time + max_search_time);
+ slot_timeout_pos = min_timeout_pos = tiw->pos;
+ if (search_all)
+ min_timeout_pos += ERTS_MONOTONIC_TO_CLKTCKS(ERTS_MONOTONIC_DAY);
+ else
+ min_timeout_pos = ERTS_MONOTONIC_TO_CLKTCKS(curr_time + max_search_time);
start_ix = tiw_pos_ix = (int) (tiw->pos & (ERTS_TIW_SIZE-1));
do {
- slot_timeout_pos++;
- if (slot_timeout_pos >= min_timeout_pos) {
- true_min_timeout = 0;
+ if (++slot_timeout_pos >= min_timeout_pos)
break;
- }
p = tiw->w[tiw_pos_ix];
@@ -269,24 +270,16 @@ remove_timer(ErtsTimerWheel *tiw, ErtsTWheelTimer *p)
p->slot = ERTS_TWHEEL_SLOT_INACTIVE;
-#if 0
- p->next = NULL;
- p->prev = NULL;
-#endif
-
tiw->nto--;
}
ErtsMonotonicTime
erts_check_next_timeout_time(ErtsSchedulerData *esdp)
{
- /*
- * Called before a scheduler is about to wait. We wont
- * check more than 10 minutes into the future.
- */
- return find_next_timeout(esdp->timer_wheel,
- erts_get_monotonic_time(esdp),
- ERTS_SEC_TO_MONOTONIC(10*60));
+ ErtsTimerWheel *tiw = esdp->timer_wheel;
+ if (tiw->true_next_timeout_time)
+ return tiw->next_timeout_time;
+ return find_next_timeout(esdp, tiw, 1, 0, 0);
}
#ifndef ERTS_TW_DEBUG
@@ -330,14 +323,11 @@ timeout_timer(ErtsTWheelTimer *p)
{
ErlTimeoutProc timeout;
void *arg;
-#if 0
- p->next = NULL;
- p->prev = NULL;
-#endif
p->slot = ERTS_TWHEEL_SLOT_INACTIVE;
timeout = p->u.func.timeout;
arg = p->u.func.arg;
(*timeout)(arg);
+ ASSERT_NO_LOCKED_LOCKS;
}
void
@@ -508,7 +498,7 @@ erts_bump_timers(ErtsTimerWheel *tiw, ErtsMonotonicTime curr_time)
tiw->next_timeout_time = curr_time + ERTS_MONOTONIC_DAY;
/* Search at most two seconds ahead... */
- (void) find_next_timeout(tiw, curr_time, ERTS_SEC_TO_MONOTONIC(2));
+ (void) find_next_timeout(NULL, tiw, 0, curr_time, ERTS_SEC_TO_MONOTONIC(2));
}
Uint