summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/plan9/profile.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-02-17 13:25:24 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-02-17 13:25:24 +0100
commit2c5c78425516590e894c9c334182073fcc56a10b (patch)
treeec4c8b58ec1d8144936bf8111382a6e7141d55c0 /sys/src/ape/lib/ap/plan9/profile.c
parent87fcb107ef333f5dce7618e0f4c73d69ebc75eb5 (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/profile.c')
-rw-r--r--sys/src/ape/lib/ap/plan9/profile.c27
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 */