diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-17 13:25:24 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2014-02-17 13:25:24 +0100 |
commit | 2c5c78425516590e894c9c334182073fcc56a10b (patch) | |
tree | ec4c8b58ec1d8144936bf8111382a6e7141d55c0 /sys/src/ape/lib/ap/plan9 | |
parent | 87fcb107ef333f5dce7618e0f4c73d69ebc75eb5 (diff) |
prof: properly save and restore RARG for amd64
amd64 passes first argument in RARG (BP) register
which has the be preserved duing _profin() and
_profout() calls. to handle this we introduce
_saveret() and _savearg(). _saveret() returns
AX, _savearg() returns RARG (BP). for archs other
and amd64, _saveret() and _savearg() are the
same function, doing nothing.
restoing works with dummy function:
uintptr
_restore(uintptr, uintptr ret)
{
return ret;
}
...
ret = _saveret();
arg = _savearg();
...
return _restore(arg, ret);
as we pass arg as the first argument, RARG (BP) is
restored.
Diffstat (limited to 'sys/src/ape/lib/ap/plan9')
-rw-r--r-- | sys/src/ape/lib/ap/plan9/profile.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/sys/src/ape/lib/ap/plan9/profile.c b/sys/src/ape/lib/ap/plan9/profile.c index a69e65f2b..969a74076 100644 --- a/sys/src/ape/lib/ap/plan9/profile.c +++ b/sys/src/ape/lib/ap/plan9/profile.c @@ -23,7 +23,8 @@ typedef unsigned long long uvlong; extern void* sbrk(ulong); extern long _callpc(void**); -extern long _savearg(void); +extern void* _savearg(void); +extern void* _saveret(void); extern void _cycles(uvlong*); /* 64-bit value of the cycle counter if there is one, 0 if there isn't */ static ulong khz; @@ -43,20 +44,27 @@ struct Plink #pragma profile off -ulong +static void* +_restore(void*, void *ret) +{ + return ret; +} + +void* _profin(void) { void *dummy; long pc; Plink *pp, *p; - ulong arg; + void *ret, *arg; vlong t; + ret = _saveret(); arg = _savearg(); pc = _callpc(&dummy); pp = _tos->prof.pp; if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid)) - return arg; + return _restore(arg, ret); for(p=pp->down; p; p=p->link) if(p->pc == pc) @@ -65,7 +73,7 @@ _profin(void) if(p >= _tos->prof.last){ _tos->prof.pp = 0; perr++; - return arg; + return _restore(arg, ret); } _tos->prof.next = p; p->link = pp->down; @@ -96,16 +104,17 @@ out: p->time = p->time - _tos->clock; break; } - return arg; /* disgusting linkage */ + return _restore(arg, ret); } -ulong +void* _profout(void) { Plink *p; - ulong arg; + void *ret, *arg; vlong t; + ret = _saveret(); arg = _savearg(); p = _tos->prof.pp; if (p == NULL || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid)) @@ -127,7 +136,7 @@ _profout(void) break; } _tos->prof.pp = p->old; - return arg; + return _restore(arg, ret); } /* stdio may not be ready for us yet */ |