Commit e77c2fe3 authored by Aram Hăvărneanu's avatar Aram Hăvărneanu

runtime: allow sysvicall functions to be called from Go

Convert them to Go in the process.

LGTM=dvyukov, dave
R=khr, dvyukov, rsc, dave
CC=golang-codereviews
https://golang.org/cl/131600043
parent 73f5010d
...@@ -84,35 +84,31 @@ extern uintptr libc·port_getn; ...@@ -84,35 +84,31 @@ extern uintptr libc·port_getn;
int32 int32
runtime·fcntl(int32 fd, int32 cmd, uintptr arg) runtime·fcntl(int32 fd, int32 cmd, uintptr arg)
{ {
return runtime·sysvicall6(libc·fcntl, 3, return runtime·sysvicall3(libc·fcntl, (uintptr)fd, (uintptr)cmd, (uintptr)arg);
(uintptr)fd, (uintptr)cmd, (uintptr)arg);
} }
int32 int32
runtime·port_create(void) runtime·port_create(void)
{ {
return runtime·sysvicall6(libc·port_create, 0); return runtime·sysvicall0(libc·port_create);
} }
int32 int32
runtime·port_associate(int32 port, int32 source, uintptr object, int32 events, uintptr user) runtime·port_associate(int32 port, int32 source, uintptr object, int32 events, uintptr user)
{ {
return runtime·sysvicall6(libc·port_associate, return runtime·sysvicall5(libc·port_associate, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
5, (uintptr)port, (uintptr)source, object, (uintptr)events, user);
} }
int32 int32
runtime·port_dissociate(int32 port, int32 source, uintptr object) runtime·port_dissociate(int32 port, int32 source, uintptr object)
{ {
return runtime·sysvicall6(libc·port_dissociate, return runtime·sysvicall3(libc·port_dissociate, (uintptr)port, (uintptr)source, object);
3, (uintptr)port, (uintptr)source, object);
} }
int32 int32
runtime·port_getn(int32 port, PortEvent *evs, uint32 max, uint32 *nget, Timespec *timeout) runtime·port_getn(int32 port, PortEvent *evs, uint32 max, uint32 *nget, Timespec *timeout)
{ {
return runtime·sysvicall6(libc·port_getn, 5, (uintptr)port, return runtime·sysvicall5(libc·port_getn, (uintptr)port, (uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
(uintptr)evs, (uintptr)max, (uintptr)nget, (uintptr)timeout);
} }
static int32 portfd = -1; static int32 portfd = -1;
......
...@@ -97,21 +97,6 @@ extern SigTab runtime·sigtab[]; ...@@ -97,21 +97,6 @@ extern SigTab runtime·sigtab[];
static Sigset sigset_none; static Sigset sigset_none;
static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, }; static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
// Calling sysvcall on os stack.
#pragma textflag NOSPLIT
uintptr
runtime·sysvicall6(uintptr fn, int32 count, ...)
{
runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch));
g->m->libcall.fn = (void*)fn;
g->m->libcall.n = (uintptr)count;
for(;count; count--)
g->m->scratch.v[count - 1] = *((uintptr*)&count + count);
g->m->libcall.args = (uintptr*)&g->m->scratch.v[0];
runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall);
return g->m->libcall.r1;
}
static int32 static int32
getncpu(void) getncpu(void)
{ {
...@@ -403,37 +388,37 @@ runtime·semawakeup(M *mp) ...@@ -403,37 +388,37 @@ runtime·semawakeup(M *mp)
int32 int32
runtime·close(int32 fd) runtime·close(int32 fd)
{ {
return runtime·sysvicall6(libc·close, 1, (uintptr)fd); return runtime·sysvicall1(libc·close, (uintptr)fd);
} }
void void
runtime·exit(int32 r) runtime·exit(int32 r)
{ {
runtime·sysvicall6(libc·exit, 1, (uintptr)r); runtime·sysvicall1(libc·exit, (uintptr)r);
} }
/* int32 */ void /* int32 */ void
runtime·getcontext(Ucontext* context) runtime·getcontext(Ucontext* context)
{ {
runtime·sysvicall6(libc·getcontext, 1, (uintptr)context); runtime·sysvicall1(libc·getcontext, (uintptr)context);
} }
int32 int32
runtime·getrlimit(int32 res, Rlimit* rlp) runtime·getrlimit(int32 res, Rlimit* rlp)
{ {
return runtime·sysvicall6(libc·getrlimit, 2, (uintptr)res, (uintptr)rlp); return runtime·sysvicall2(libc·getrlimit, (uintptr)res, (uintptr)rlp);
} }
uint8* uint8*
runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off) runtime·mmap(byte* addr, uintptr len, int32 prot, int32 flags, int32 fildes, uint32 off)
{ {
return (uint8*)runtime·sysvicall6(libc·mmap, 6, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off); return (uint8*)runtime·sysvicall6(libc·mmap, (uintptr)addr, (uintptr)len, (uintptr)prot, (uintptr)flags, (uintptr)fildes, (uintptr)off);
} }
void void
runtime·munmap(byte* addr, uintptr len) runtime·munmap(byte* addr, uintptr len)
{ {
runtime·sysvicall6(libc·munmap, 2, (uintptr)addr, (uintptr)len); runtime·sysvicall2(libc·munmap, (uintptr)addr, (uintptr)len);
} }
extern int64 runtime·nanotime1(void); extern int64 runtime·nanotime1(void);
...@@ -441,7 +426,7 @@ extern int64 runtime·nanotime1(void); ...@@ -441,7 +426,7 @@ extern int64 runtime·nanotime1(void);
int64 int64
runtime·nanotime(void) runtime·nanotime(void)
{ {
return runtime·sysvicall6((uintptr)runtime·nanotime1, 0); return runtime·sysvicall0((uintptr)runtime·nanotime1);
} }
void void
...@@ -459,113 +444,113 @@ time·now(int64 sec, int32 usec) ...@@ -459,113 +444,113 @@ time·now(int64 sec, int32 usec)
int32 int32
runtime·open(int8* path, int32 oflag, int32 mode) runtime·open(int8* path, int32 oflag, int32 mode)
{ {
return runtime·sysvicall6(libc·open, 3, (uintptr)path, (uintptr)oflag, (uintptr)mode); return runtime·sysvicall3(libc·open, (uintptr)path, (uintptr)oflag, (uintptr)mode);
} }
int32 int32
runtime·pthread_attr_destroy(PthreadAttr* attr) runtime·pthread_attr_destroy(PthreadAttr* attr)
{ {
return runtime·sysvicall6(libc·pthread_attr_destroy, 1, (uintptr)attr); return runtime·sysvicall1(libc·pthread_attr_destroy, (uintptr)attr);
} }
int32 int32
runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size) runtime·pthread_attr_getstack(PthreadAttr* attr, void** addr, uint64* size)
{ {
return runtime·sysvicall6(libc·pthread_attr_getstack, 3, (uintptr)attr, (uintptr)addr, (uintptr)size); return runtime·sysvicall3(libc·pthread_attr_getstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
} }
int32 int32
runtime·pthread_attr_init(PthreadAttr* attr) runtime·pthread_attr_init(PthreadAttr* attr)
{ {
return runtime·sysvicall6(libc·pthread_attr_init, 1, (uintptr)attr); return runtime·sysvicall1(libc·pthread_attr_init, (uintptr)attr);
} }
int32 int32
runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state) runtime·pthread_attr_setdetachstate(PthreadAttr* attr, int32 state)
{ {
return runtime·sysvicall6(libc·pthread_attr_setdetachstate, 2, (uintptr)attr, (uintptr)state); return runtime·sysvicall2(libc·pthread_attr_setdetachstate, (uintptr)attr, (uintptr)state);
} }
int32 int32
runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size) runtime·pthread_attr_setstack(PthreadAttr* attr, void* addr, uint64 size)
{ {
return runtime·sysvicall6(libc·pthread_attr_setstack, 3, (uintptr)attr, (uintptr)addr, (uintptr)size); return runtime·sysvicall3(libc·pthread_attr_setstack, (uintptr)attr, (uintptr)addr, (uintptr)size);
} }
int32 int32
runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg) runtime·pthread_create(Pthread* thread, PthreadAttr* attr, void(*fn)(void), void *arg)
{ {
return runtime·sysvicall6(libc·pthread_create, 4, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg); return runtime·sysvicall4(libc·pthread_create, (uintptr)thread, (uintptr)attr, (uintptr)fn, (uintptr)arg);
} }
/* int32 */ void /* int32 */ void
runtime·raise(int32 sig) runtime·raise(int32 sig)
{ {
runtime·sysvicall6(libc·raise, 1, (uintptr)sig); runtime·sysvicall1(libc·raise, (uintptr)sig);
} }
int32 int32
runtime·read(int32 fd, void* buf, int32 nbyte) runtime·read(int32 fd, void* buf, int32 nbyte)
{ {
return runtime·sysvicall6(libc·read, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte); return runtime·sysvicall3(libc·read, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
} }
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
int32 int32
runtime·sem_init(SemT* sem, int32 pshared, uint32 value) runtime·sem_init(SemT* sem, int32 pshared, uint32 value)
{ {
return runtime·sysvicall6(libc·sem_init, 3, (uintptr)sem, (uintptr)pshared, (uintptr)value); return runtime·sysvicall3(libc·sem_init, (uintptr)sem, (uintptr)pshared, (uintptr)value);
} }
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
int32 int32
runtime·sem_post(SemT* sem) runtime·sem_post(SemT* sem)
{ {
return runtime·sysvicall6(libc·sem_post, 1, (uintptr)sem); return runtime·sysvicall1(libc·sem_post, (uintptr)sem);
} }
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
int32 int32
runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout) runtime·sem_reltimedwait_np(SemT* sem, Timespec* timeout)
{ {
return runtime·sysvicall6(libc·sem_reltimedwait_np, 2, (uintptr)sem, (uintptr)timeout); return runtime·sysvicall2(libc·sem_reltimedwait_np, (uintptr)sem, (uintptr)timeout);
} }
#pragma textflag NOSPLIT #pragma textflag NOSPLIT
int32 int32
runtime·sem_wait(SemT* sem) runtime·sem_wait(SemT* sem)
{ {
return runtime·sysvicall6(libc·sem_wait, 1, (uintptr)sem); return runtime·sysvicall1(libc·sem_wait, (uintptr)sem);
} }
/* int32 */ void /* int32 */ void
runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue) runtime·setitimer(int32 which, Itimerval* value, Itimerval* ovalue)
{ {
runtime·sysvicall6(libc·setitimer, 3, (uintptr)which, (uintptr)value, (uintptr)ovalue); runtime·sysvicall3(libc·setitimer, (uintptr)which, (uintptr)value, (uintptr)ovalue);
} }
/* int32 */ void /* int32 */ void
runtime·sigaction(int32 sig, struct Sigaction* act, struct Sigaction* oact) runtime·sigaction(int32 sig, struct Sigaction* act, struct Sigaction* oact)
{ {
runtime·sysvicall6(libc·sigaction, 3, (uintptr)sig, (uintptr)act, (uintptr)oact); runtime·sysvicall3(libc·sigaction, (uintptr)sig, (uintptr)act, (uintptr)oact);
} }
/* int32 */ void /* int32 */ void
runtime·sigaltstack(Sigaltstack* ss, Sigaltstack* oss) runtime·sigaltstack(Sigaltstack* ss, Sigaltstack* oss)
{ {
runtime·sysvicall6(libc·sigaltstack, 2, (uintptr)ss, (uintptr)oss); runtime·sysvicall2(libc·sigaltstack, (uintptr)ss, (uintptr)oss);
} }
/* int32 */ void /* int32 */ void
runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset) runtime·sigprocmask(int32 how, Sigset* set, Sigset* oset)
{ {
runtime·sysvicall6(libc·sigprocmask, 3, (uintptr)how, (uintptr)set, (uintptr)oset); runtime·sysvicall3(libc·sigprocmask, (uintptr)how, (uintptr)set, (uintptr)oset);
} }
int64 int64
runtime·sysconf(int32 name) runtime·sysconf(int32 name)
{ {
return runtime·sysvicall6(libc·sysconf, 1, (uintptr)name); return runtime·sysvicall1(libc·sysconf, (uintptr)name);
} }
extern void runtime·usleep1(uint32); extern void runtime·usleep1(uint32);
...@@ -580,7 +565,7 @@ runtime·usleep(uint32 µs) ...@@ -580,7 +565,7 @@ runtime·usleep(uint32 µs)
int32 int32
runtime·write(uintptr fd, void* buf, int32 nbyte) runtime·write(uintptr fd, void* buf, int32 nbyte)
{ {
return runtime·sysvicall6(libc·write, 3, (uintptr)fd, (uintptr)buf, (uintptr)nbyte); return runtime·sysvicall3(libc·write, (uintptr)fd, (uintptr)buf, (uintptr)nbyte);
} }
extern void runtime·osyield1(void); extern void runtime·osyield1(void);
...@@ -592,7 +577,7 @@ runtime·osyield(void) ...@@ -592,7 +577,7 @@ runtime·osyield(void)
// Check the validity of m because we might be called in cgo callback // Check the validity of m because we might be called in cgo callback
// path early enough where there isn't a m available yet. // path early enough where there isn't a m available yet.
if(g && g->m != nil) { if(g && g->m != nil) {
runtime·sysvicall6(libc·sched_yield, 0); runtime·sysvicall0(libc·sched_yield);
return; return;
} }
runtime·osyield1(); runtime·osyield1();
......
...@@ -12,7 +12,6 @@ func sigaltstack(new, old unsafe.Pointer) ...@@ -12,7 +12,6 @@ func sigaltstack(new, old unsafe.Pointer)
func sigprocmask(mode int32, new, old unsafe.Pointer) func sigprocmask(mode int32, new, old unsafe.Pointer)
func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
func getrlimit(kind int32, limit unsafe.Pointer) func getrlimit(kind int32, limit unsafe.Pointer)
func asmsysvicall6(fn unsafe.Pointer)
func miniterrno(fn unsafe.Pointer) func miniterrno(fn unsafe.Pointer)
func raise(sig int32) func raise(sig int32)
func getcontext(ctxt unsafe.Pointer) func getcontext(ctxt unsafe.Pointer)
...@@ -20,3 +19,77 @@ func tstart_sysvicall(mm unsafe.Pointer) uint32 ...@@ -20,3 +19,77 @@ func tstart_sysvicall(mm unsafe.Pointer) uint32
func nanotime1() int64 func nanotime1() int64
func usleep1(usec uint32) func usleep1(usec uint32)
func osyield1() func osyield1()
type libcFunc byte
var asmsysvicall6 libcFunc
//go:nosplit
func sysvicall0(fn *libcFunc) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 0
libcall.args = unsafe.Pointer(fn) // it's unused but must be non-nil, otherwise crashes
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
//go:nosplit
func sysvicall1(fn *libcFunc, a1 uintptr) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 1
libcall.args = noescape(unsafe.Pointer(&a1))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
//go:nosplit
func sysvicall2(fn *libcFunc, a1, a2 uintptr) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 2
libcall.args = noescape(unsafe.Pointer(&a1))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
//go:nosplit
func sysvicall3(fn *libcFunc, a1, a2, a3 uintptr) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 3
libcall.args = noescape(unsafe.Pointer(&a1))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
//go:nosplit
func sysvicall4(fn *libcFunc, a1, a2, a3, a4 uintptr) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 4
libcall.args = noescape(unsafe.Pointer(&a1))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
//go:nosplit
func sysvicall5(fn *libcFunc, a1, a2, a3, a4, a5 uintptr) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 5
libcall.args = noescape(unsafe.Pointer(&a1))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
//go:nosplit
func sysvicall6(fn *libcFunc, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
libcall := &getg().m.libcall
libcall.fn = unsafe.Pointer(fn)
libcall.n = 6
libcall.args = noescape(unsafe.Pointer(&a1))
asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(libcall))
return libcall.r1
}
...@@ -40,12 +40,15 @@ struct Rlimit { ...@@ -40,12 +40,15 @@ struct Rlimit {
}; };
int32 runtime·getrlimit(int32, Rlimit*); int32 runtime·getrlimit(int32, Rlimit*);
// Call a library function with SysV conventions, // Call an external library function described by {fn, a0, ..., an}, with
// and switch to os stack during the call. // SysV conventions, switching to os stack during the call, if necessary.
#pragma varargck countpos runtime·sysvicall6 2 uintptr runtime·sysvicall0(uintptr fn);
#pragma varargck type runtime·sysvicall6 uintptr uintptr runtime·sysvicall1(uintptr fn, uintptr a1);
#pragma varargck type runtime·sysvicall6 int32 uintptr runtime·sysvicall2(uintptr fn, uintptr a1, uintptr a2);
uintptr runtime·sysvicall3(uintptr fn, uintptr a1, uintptr a2, uintptr a3);
uintptr runtime·sysvicall4(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
uintptr runtime·sysvicall5(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
uintptr runtime·sysvicall6(uintptr fn, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
void runtime·asmsysvicall6(void *c); void runtime·asmsysvicall6(void *c);
uintptr runtime·sysvicall6(uintptr fn, int32 count, ...);
void runtime·miniterrno(void *fn); void runtime·miniterrno(void *fn);
...@@ -248,7 +248,7 @@ struct GCStats ...@@ -248,7 +248,7 @@ struct GCStats
struct LibCall struct LibCall
{ {
void (*fn)(void*); void* fn;
uintptr n; // number of parameters uintptr n; // number of parameters
void* args; // parameters void* args; // parameters
uintptr r1; // return values uintptr r1; // return values
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment