Commit 5c303259 authored by Hector Chu's avatar Hector Chu Committed by Russ Cox

runtime: eliminate handle churn when churning channels on Windows

The Windows implementation of the net package churns through a couple of channels for every read/write operation.  This translates into a lot of time spent in the kernel creating and deleting event objects.

R=rsc, dvyukov, alex.brainman, jp
CC=golang-dev
https://golang.org/cl/4997044
parent e076c502
...@@ -603,8 +603,6 @@ runtime·gc(int32 force) ...@@ -603,8 +603,6 @@ runtime·gc(int32 force)
m->gcing = 1; m->gcing = 1;
runtime·stoptheworld(); runtime·stoptheworld();
if(runtime·mheap.Lock.key != 0)
runtime·throw("runtime·mheap locked during gc");
cachestats(); cachestats();
heap0 = mstats.heap_alloc; heap0 = mstats.heap_alloc;
......
...@@ -119,10 +119,10 @@ enum ...@@ -119,10 +119,10 @@ enum
*/ */
struct Lock struct Lock
{ {
uint32 key;
#ifdef __WINDOWS__ #ifdef __WINDOWS__
void* event; M* waitm; // linked list of waiting M's
#else #else
uint32 key;
uint32 sema; // for OS X uint32 sema; // for OS X
#endif #endif
}; };
...@@ -251,6 +251,11 @@ struct M ...@@ -251,6 +251,11 @@ struct M
uint32 freglo[16]; // D[i] lsb and F[i] uint32 freglo[16]; // D[i] lsb and F[i]
uint32 freghi[16]; // D[i] msb and F[i+16] uint32 freghi[16]; // D[i] msb and F[i+16]
uint32 fflag; // floating point compare flags uint32 fflag; // floating point compare flags
#ifdef __WINDOWS__
void* event; // event for signalling
M* nextwaitm; // next M waiting for lock
#endif
}; };
struct Stktop struct Stktop
......
...@@ -40,14 +40,12 @@ extern void *runtime·WaitForSingleObject; ...@@ -40,14 +40,12 @@ extern void *runtime·WaitForSingleObject;
extern void *runtime·WriteFile; extern void *runtime·WriteFile;
static int64 timerfreq; static int64 timerfreq;
static void destroylock(Lock *l);
void void
runtime·osinit(void) runtime·osinit(void)
{ {
runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq); runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq);
runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1); runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
runtime·destroylock = destroylock;
} }
void void
...@@ -120,22 +118,50 @@ initevent(void **pevent) ...@@ -120,22 +118,50 @@ initevent(void **pevent)
} }
} }
#define LOCK_HELD ((M*)-1)
static void static void
eventlock(Lock *l) eventlock(Lock *l)
{ {
// Allocate event if needed. // Allocate event if needed.
if(l->event == 0) if(m->event == nil)
initevent(&l->event); initevent(&m->event);
for(;;) {
m->nextwaitm = runtime·atomicloadp(&l->waitm);
if(m->nextwaitm == nil) {
if(runtime·casp(&l->waitm, nil, LOCK_HELD))
return;
// Someone else has it.
// l->waitm points to a linked list of M's waiting
// for this lock, chained through m->nextwaitm.
// Queue this M.
} else if(runtime·casp(&l->waitm, m->nextwaitm, m))
break;
}
if(runtime·xadd(&l->key, 1) > 1) // someone else has it; wait // Wait.
runtime·stdcall(runtime·WaitForSingleObject, 2, l->event, (uintptr)-1); runtime·stdcall(runtime·WaitForSingleObject, 2, m->event, (uintptr)-1);
} }
static void static void
eventunlock(Lock *l) eventunlock(Lock *l)
{ {
if(runtime·xadd(&l->key, -1) > 0) // someone else is waiting M *mp;
runtime·stdcall(runtime·SetEvent, 1, l->event);
for(;;) {
mp = runtime·atomicloadp(&l->waitm);
if(mp == LOCK_HELD) {
if(runtime·casp(&l->waitm, LOCK_HELD, nil))
return;
// Other M's are waiting for the lock.
// Dequeue a M.
} else if(runtime·casp(&l->waitm, mp, mp->nextwaitm))
break;
}
// Wake that M.
runtime·stdcall(runtime·SetEvent, 1, mp->event);
} }
void void
...@@ -156,17 +182,10 @@ runtime·unlock(Lock *l) ...@@ -156,17 +182,10 @@ runtime·unlock(Lock *l)
eventunlock(l); eventunlock(l);
} }
static void
destroylock(Lock *l)
{
if(l->event != 0)
runtime·stdcall(runtime·CloseHandle, 1, l->event);
}
void void
runtime·noteclear(Note *n) runtime·noteclear(Note *n)
{ {
n->lock.key = 0; // memset(n, 0, sizeof *n) n->lock.waitm = nil;
eventlock(&n->lock); eventlock(&n->lock);
} }
......
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