#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include #include enum{ Reset = 0, Init, Shutdown, Attach, Walk, Stat, Open, Create, Close, Read, Bread, Write, Bwrite, Remove, Wstat, Power, Config, NFunc }; char *funcname[] = { [Reset] = "reset", [Init] = "init", [Shutdown] = "shutdown", [Attach] = "attach", [Walk] = "walk", [Stat] = "stat", [Open] = "open", [Create] = "create", [Close] = "close", [Read] = "read", [Bread] = "bread", [Write] = "bwrite", [Bwrite] = "bwrite", [Remove] = "remove", [Wstat] = "wstat", [Power] = "power", [Config] = "config", [NFunc] = "nfunc", }; static DTProbe **dtpentry, **dtpreturn; static int ndev = 0; static void ***functab = nil; static void **wraptab = nil; #define WRAPV1(x,y,type0)\ void x(type0 α){\ DTTrigInfo info;\ ulong i;\ void (*p)(type0);\ memset(&info, 0, sizeof(info));\ info.arg[0] = (uvlong) α;\ i = α->type*NFunc + y;\ dtptrigger(dtpentry[i], &info);\ p = wraptab[i];\ p(α);\ dtptrigger(dtpreturn[i], &info);\ } #define WRAP2(x,y,rtype,type0,type1)\ rtype x(type0 α, type1 β){\ DTTrigInfo info;\ rtype rc;\ ulong i;\ rtype (*p)(type0,type1);\ memset(&info, 0, sizeof(info));\ info.arg[0] = (uvlong) α;\ info.arg[1] = (uvlong) β;\ i = α->type*NFunc + y;\ dtptrigger(dtpentry[i], &info);\ p = wraptab[i];\ rc = p(α, β);\ info.arg[9] = (uvlong) rc;\ dtptrigger(dtpreturn[i], &info);\ return rc;\ } #define WRAP3(x,y,rtype,type0,type1,type2)\ rtype x(type0 α, type1 β, type2 γ){\ DTTrigInfo info;\ rtype rc;\ ulong i;\ rtype (*p)(type0,type1,type2);\ memset(&info, 0, sizeof(info));\ info.arg[0] = (uvlong) α;\ info.arg[1] = (uvlong) β;\ info.arg[2] = (uvlong) γ;\ i = α->type*NFunc + y;\ dtptrigger(dtpentry[i], &info);\ p = wraptab[i];\ rc = p(α, β, γ);\ info.arg[9] = (uvlong) rc;\ dtptrigger(dtpreturn[i], &info);\ return rc;\ } #define WRAP4(x,y,rtype,type0,type1,type2,type3)\ rtype x(type0 α, type1 β, type2 γ, type3 δ){\ DTTrigInfo info;\ rtype rc;\ ulong i;\ rtype (*p)(type0,type1,type2,type3);\ memset(&info, 0, sizeof(info));\ info.arg[0] = (uvlong) α;\ info.arg[1] = (uvlong) β;\ info.arg[2] = (uvlong) γ;\ info.arg[3] = (uvlong) δ;\ i = α->type*NFunc + y;\ dtptrigger(dtpentry[i], &info);\ p = wraptab[i];\ rc = p(α, β, γ, δ);\ info.arg[9] = (uvlong) rc;\ dtptrigger(dtpreturn[i], &info);\ return rc;\ } WRAP4(dtwrap_walk, Walk, Walkqid*, Chan*, Chan*, char**, int); WRAP3(dtwrap_stat, Stat, int, Chan*, uchar*, int); WRAP2(dtwrap_open, Open, Chan*, Chan*, int); WRAP4(dtwrap_create, Create, Chan*, Chan*, char*, int, ulong); WRAPV1(dtwrap_close, Close, Chan*); WRAP4(dtwrap_read, Read, long, Chan*, void*, long, vlong); WRAP3(dtwrap_bread, Bread, Block*, Chan*, long, ulong); WRAP4(dtwrap_write, Write, long, Chan*, void*, long, vlong); WRAP3(dtwrap_bwrite, Bwrite, long, Chan*, Block*, ulong); WRAPV1(dtwrap_remove, Remove, Chan*); WRAP3(dtwrap_wstat, Wstat, int, Chan*, uchar*, int); static void devprovide(DTProvider *prov) { uintptr n; static int provided; char pname[64]; void **fp; int i, j; ulong sz; if(provided) return; provided = 1; if(ndev == 0){ for(i=0; devtab[i] != nil; i++) ; ndev = i; } sz = sizeof(void*) * ndev * NFunc; dtpentry = smalloc(sz); dtpreturn = smalloc(sz); if(functab == nil) functab = smalloc(sz); if(wraptab == nil) wraptab = smalloc(sz); memset(functab, 0, sz); memset(wraptab, 0, sz); for(i=0,n=0; ireset; for(j=0; jdc == L'Δ') continue; functab[n] = fp; switch(j){ case Walk: wraptab[n] = dtwrap_walk; break; case Stat: wraptab[n] = dtwrap_stat; break; case Open: wraptab[n] = dtwrap_open; break; case Create: wraptab[n] = dtwrap_create; break; case Close: wraptab[n] = dtwrap_close; break; case Read: wraptab[n] = dtwrap_read; break; case Bread: wraptab[n] = dtwrap_bread; break; case Write: wraptab[n] = dtwrap_write; break; case Bwrite: wraptab[n] = dtwrap_bwrite; break; case Remove: wraptab[n] = dtwrap_remove; break; case Wstat: wraptab[n] = dtwrap_wstat; break; default: continue; } snprint(pname, sizeof(pname), "dev:%C:%s:entry", devtab[i]->dc, funcname[j]); dtpentry[n] = dtpnew(pname, prov, (void *) n); snprint(pname, sizeof(pname), "dev:%C:%s:return", devtab[i]->dc, funcname[j]); dtpreturn[n] = dtpnew(pname, prov, (void *) n); } } } static int devenable(DTProbe *p) { uintptr n; void *z; n = (uintptr) p->aux; assert(n > 0 && n < ndev*NFunc); if(dtpentry[n]->nenable + dtpreturn[n]->nenable == 0){ /* print("src(%#p) // *functab[n]:%#p enabling %zd,%zd wraptab[n]%#p\n", functab[n], *functab[n], n/(NFunc-1), n%(NFunc), wraptab[n]); */ z = *functab[n], *functab[n] = wraptab[n], wraptab[n] = z; } return 0; } static void devdisable(DTProbe *p) { uintptr n; void *z; n = (uintptr)p->aux; assert(n > 0 && n < ndev*NFunc); if(dtpentry[n]->nenable + dtpreturn[n]->nenable == 0){ /* print("src(%#p) // disabling %zd,%zd wraptab[n]%#p\n", functab[n], n/(NFunc-1), n%(NFunc), wraptab[n]); */ z = *functab[n], *functab[n] = wraptab[n], wraptab[n] = z; } } DTProvider dtracydevprov = { .name = "dev", .provide = devprovide, .enable = devenable, .disable = devdisable, };